zoukankan      html  css  js  c++  java
  • 118.Java反射-工厂模式

    反射

    类字节码文件是在硬盘上存储的,是一个个的.class文件。我们在new一个对象时,JVM会先把字节码文件的信息读出来放到内存中,第二次用时,就不用在加载了,而是直接使用之前缓存的这个字节码信息。

    字节码的信息包括:类名、声明的方法、声明的字段等信息。在Java中“万物皆对象”,这些信息当然也需要封装一个对象,这就是Class类、Method类、Field类。

    通过Class类、Method类、Field类等等类可以得到这个类型的一些信息,甚至可以不用new关键字就创建一个实例,可以执行一个对象中的方法,设置或获取字段的值,这就是反射技术

     Class类

     获取Class对象的三种方式

    Java中有一个Class类用于代表某一个类的字节码。

    Java提供了三种方式获取类的字节码

       forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装

       类名.class

       对象.getClass()

    /**
         * 加载类的字节码的3种方式
         * @throws Exception
         * */
        public void test1() throws Exception {
            // 方式一
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            // 方式二
            Class clazz2 = Person.class;
            // 方式三
            Person p1 = new Person();
            Class clazz3 = p1.getClass();
        }

    通过Class类获取类型的一些信息

    1. getName()类的名称(全名,全限定名)

    2 getSimpleName()类的的简单名称(不带包名)

    3. getModifiers(); 类的的修饰符

    4.创建对象

       无参数构造创建对象

       newInstance()

    5. 获取指定参数的构造器对象,并可以使用Constructor对象创建一个实例

        Constructor<T> getConstructor(Class<?>... parameterTypes)

    /**
         * 通过Class对象获取类的一些信息
         * 
         * @throws Exception
         * */
        private static void test2() throws Exception {
    
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            // 获取类的名称
            String name = clazz1.getName();
            System.out.println(name); // cn.itcast.gz.reflect.Person
            // 获取类的简单名称
            System.out.println(clazz1.getSimpleName()); // Person
            // 获取类的修饰符
            int modifiers = clazz1.getModifiers();
            System.out.println(modifiers);
            // 构建对象(默认调用无参数构造.)
            Object ins = clazz1.newInstance();
            Person p = (Person) ins;
            System.out.println(p); // cn.itcast.gz.reflect.Person@c17164
            // 获取指定参数的构造函数
            Constructor<?> con = clazz1.getConstructor(String.class, int.class);
            // 使用Constructor创建对象.
            Object p1 = con.newInstance("jack", 28);
            System.out.println(((Person) p1).getName());
        }

    通过Class类获取类型中的方法的信息

    1.获取公共方法包括继承的父类的方法

       getMethods()返回一个数组,元素类型是Method

    2.获取指定参数的公共方法

       getMethod("setName", String.class);

    3.获得所有的方法,包括私有

       Method[] getDeclaredMethods() 

    4.获得指定参数的方法,包括私有

       Method getDeclaredMethod(String name, Class<?>... parameterTypes)

        /**
         * 获取公有方法.
         * @throws Exception
         * */
        private static void test3() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            // 1.获取非私用方法(包括父类继承的方法)
            Method[] methods = clazz1.getMethods();
            System.out.println(methods.length);
            for (Method m : methods) {
                // System.out.println(m.getName());
                if ("eat".equals(m.getName())) {
                    m.invoke(clazz1.newInstance(), null);
                }
            }
    
        }
    /**
         * 获取指定方法签名的方法
         * 
         * @throws Exception
         * */
        private static void test4() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            // 获取指定名称的函数
            Method method1 = clazz1.getMethod("eat", null);
            method1.invoke(new Person(), null);
        }
    /**
         * 获取指定方法名且有参数的方法
         * 
         * @throws Exception
         * */
        private static void test5() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            Method method = clazz1.getMethod("eat", String.class);
            method.invoke(new Person(), "包子");
        }
    
        /**
         * 获取指定方法名,参数列表为空的方法.
         * 
         * @throws Exception
         * */
        private static void test4() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            // 获取指定名称的函数
            Method method1 = clazz1.getMethod("eat", null);
            method1.invoke(new Person(), null);
        }
    /**
         * 反射静态方法
         * @throws Exception
         * */
        private static void test7() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            Method method = clazz1.getMethod("play", null);
            method.invoke(null, null);
        }
    
        /**
         * 访问私有方法 暴力反射
         * @throws Exception
         * */
        private static void test6() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            Method method = clazz1.getDeclaredMethod("movie", String.class);
            method.setAccessible(true);
            method.invoke(new Person(), "苍老师");
        }

    通过Class类获取类型中的字段的信息

    1.获取公共字段

       Field[] getFields() 

    2.获取指定参数的公共字段

       Field getField(String name) 

    3.获取所有的字段

       Field[] getDeclaredFields() 

    4.获取指定参数的字段,包括私用

       Field getDeclaredField(String name) 

    /**
         * 获取公有的字段
         * */
        private static void test8() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            Field[] fields = clazz1.getFields();
            Person p = new Person();
            System.out.println(fields.length);
            for (Field f : fields) {
                System.out.println(f.getName());
                if ("name".equals(f.getName())) {
                    System.out.println(f.getType().getName());
                    f.set(p, "jack");
                }
            }
            System.out.println(p.getName());
    
        }
    /**
         * 获取私有的字段
         * @throws Exception
         * */
        private static void test9() throws Exception {
            Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
            Field field = clazz1.getDeclaredField("age");
            System.out.println(field.getName());
            field.setAccessible(true);
            Person p = new Person();
            field.set(p, 100);
            System.out.println(p.getAge());
        }

    工厂模式

    Factory

    例如:汽车销售商场

    该模式将创建对象的过程放在了一个静态方法中来实现.在实际编程中,如果需要大量的创建对象,该模式是比较理想的.

    public class Demo1 {
        public static void main(String[] args) {
            System.out.println("买宝马");
            Car bmw = CarFactory("BMW");
            bmw.run();
            System.out.println("买大奔");
            Car benz = CarFactory("Benz");
            benz.run();
        }
    
        public static Car CarFactory(String carName) {
            if ("BMW".equals(carName)) {
                return new BMW();
            } else if ("Benz".equals(carName)) {
                return new Benz();
            } else {
                throw new RuntimeException("车型有误");
            }
        }
    }
    
    abstract class Car {
    
        public abstract void run();
    }
    
    class BMW extends Car {
    
        @Override
        public void run() {
            System.out.println("BMW跑跑");
        }
    }
    
    class Benz extends Car {
    
        @Override
        public void run() {
            System.out.println("Benz跑跑");
        }
    }

    模拟spring工厂:

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    class Student{
        
        private int id;
        
        private  String name;
        
        public Student(int id , String name){
            this.id = id;
            this.name = name;
        }
        
        public Student(){
            
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public String toString() {
            return this.id +"-"+this.name;
        }
        
    }
    class Person{
        
        private int age;
        
        public Person(){
            
        }
        
        
        
        
        @Override
        public String toString() {
            return this.age+"";
        }
    }
    public class Demo1 {
        
        public static void main(String[] args) throws Exception {
            Object o = getInstance();
            System.out.println(o);
            
        }
        
        public static Object getInstance() throws Exception{
            FileReader fileReader = new FileReader("src/info.txt");
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line = bufferedReader.readLine();
            Class clazz  = Class.forName(line);        
            Constructor c =  clazz.getConstructor(null);
            Object c1 = c.newInstance(null);
            while((line=bufferedReader.readLine())!=null){
                String[] datas =  line.split("=");
                Field f = clazz.getDeclaredField(datas[0]);
                f.setAccessible(true);
                if(f.getType()==int.class){
                    f.set(c1, Integer.parseInt(datas[1]));
                }else{
                //f.setAccessible(true);
                    f.set(c1,datas[1]);
                }
            }
            return c1;
        }
        
        
        
    }
    author@nohert
  • 相关阅读:
    常用类练习题(用字符串常用类判断输入的一段话是否为回文)
    面向对象综合练习题(动物乐园)
    多态练习题(通过UML建模语言来实现饲养员喂养动物)
    UML建模语言使用的概述
    多态练习题(员工使用不同的交通工具回家)
    多态练习题(宠物医院治疗小动物的问题 ,多态的应用:向上类型传递)
    接口练习题(书信接口)
    接口练习题(实现接口功能拓展的两种方法)
    Oracle rman 各种恢复
    Oracle rman 全备份的一个小例子
  • 原文地址:https://www.cnblogs.com/gzgBlog/p/13670772.html
Copyright © 2011-2022 走看看