java学习笔记(六十 一)—— 反射

概述
  • 反射是框架设计的灵魂。框架是半成品软件。在框架的基础上进行软件开发,简化编码。
  • 将类的各个组成部分封装为其他对象,称为反射机制
  • java代码在计算机中的三个阶段:Source源代码阶段、Class类对象阶段、Runtime运行时阶段
  • 反射的优点:
    • 在程序运行过程中,操作这些对象
    • 降低程序的耦合性,提高程序可扩展性
获取字节码Class对象
  • Class.forName(“全类名”):将字节码文件加载进内存,返回class对象。
  • 类名.class:通过类名的属性class获取
  • 对象.getClass:这个方法在Object类中定义
      try {
      		// Person类对象
            Class cls1 = Class.forName("Person");
            // 第一种方式:多用于配置文件
            System.out.println(cls1); // class Person
            // 第二种方式:多用于参数的传递
            Class cls2 = Person.class;
            System.out.println(cls2); // class Person
            // 第三种方式:多用于对象的获取字节码
            Person p = new Person();
            Class cls3 = p.getClass();
            System.out.println(cls3); // class Person
            System.out.println(cls1==cls2); // true
            System.out.println(cls1==cls3); // true
            // 同一个字节码文件(*.class)在一次程序的运行过程中,只会被加载一次,不管哪一种方式获取的class对象都是同一个
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    
使用class对象
  • 获取成员变量

    Field[] getFields​() 
    	返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段。  
    Field getField​(String name) 
    	返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段。 
    Field getDeclaredField​(String name) 
    	返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段。  
    Field[] getDeclaredFields​()
    	返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段。获取所有的成员变量,不考虑修饰符  
    
    Filed操作:成员变量操作
    	1、设置值,set(Object obj,Object value)
    	2、获取值,get(Object obj)
    	3、忽略权限修饰符的安全检测,称为暴力反射,setAccessible(true)
    
    public class PersonTwo {
        private String name;
        private int age;
        public String a;
        public String b;
        public String c;
        public String d;
    
        public PersonTwo() {
        }
    
        public PersonTwo(String name, int age, String a, String b, String c, String d) {
            this.name = name;
            this.age = age;
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getA() {
            return a;
        }
    
        public void setA(String a) {
            this.a = a;
        }
    
        public String getB() {
            return b;
        }
    
        public void setB(String b) {
            this.b = b;
        }
    
        public String getC() {
            return c;
        }
    
        public void setC(String c) {
            this.c = c;
        }
    
        public String getD() {
            return d;
        }
    
        public void setD(String d) {
            this.d = d;
        }
    
        @Override
        public String toString() {
            return "PersonTwo{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", a='" + a + '\'' +
                    ", b='" + b + '\'' +
                    ", c='" + c + '\'' +
                    ", d='" + d + '\'' +
                    '}';
        }
        public void eat(){
            System.out.println("chifan");
        }
    }
    
    
            Class<PersonTwo> personClass = PersonTwo.class;
            Field[] fields = personClass.getFields();
            for (Field field : fields) {
                System.out.println(field);
                // public java.lang.String Person.a,
                // public java.lang.String Person.b,
                // public java.lang.String Person.c
                // public java.lang.String Person.d
            }
            System.out.println("+++++++++++");
            try {
                Field a = personClass.getField("a");
                System.out.println(a);// public java.lang.String Person.a
                PersonTwo p1 = new PersonTwo();
                Object obj1 = a.get(p1); // 获取成员变量a的值
                System.out.println(obj1); // null
                a.set(p1,"hello"); // 对象p1,设置成员变量a的值
                System.out.println(p1);
    			
            } catch (Exception e) {
                e.printStackTrace();
            }
    
  • 获取构造方法

    Constructor<T> getConstructor​(Class<?>... parameterTypes) 
    	返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数。  
    Constructor<?>[] getConstructors​() 
    	返回一个包含 Constructor对象的数组, Constructor对象反映了由该 Class对象表示的类的所有公共构造函数。  
    Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes) 
    	返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数。  
    Constructor<?>[] getDeclaredConstructors​() 
    	返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组。  
    
        Class<PersonTwo> personClass = PersonTwo.class;
        Constructor<?>[] constructors = personClass.getConstructors();
        Constructor<PersonTwo> constructor = null;
        try {
            constructor = personClass.getConstructor(String.class,int.class,String.class,String.class,String.class,String.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        System.out.println(constructor);
        System.out.println(Arrays.toString(constructors));
       
        PersonTwo person2 = null;
        try {
         	// 创建对象
            person2 = constructor.newInstance("hello", 12, "a", "b", "c", "d");
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        System.out.println(person2); // PersonTwo{name='hello', age=12, a='a', b='b', c='c', d='d'}
    }
    
  • 获取成员方法

    方法 getMethod​(String name, Class<?>... parameterTypes) 
    	返回一个 方法对象,该对象反映由该 Class对象表示的类或接口的指定公共成员方法。 获取所有public修饰的成员变量 
    方法[] getMethods​() 
    	返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类。  
    方法 getDeclaredMethod​(String name, Class<?>... parameterTypes) 
    	返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 Class对象。  
    方法[] getDeclaredMethods​() 
    	返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承方法。 
    
        Class<PersonTwo> personClass = PersonTwo.class;
        try {
            Method eat = personClass.getMethod("eat");
            try {
                eat.invoke(new PersonTwo("hello",13,"","","","")); // eat方法执行,结果式chifan
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    
  • 获取类名

    String getName​() 
    	返回由该 Class对象表示的实体(类,接口,数组类,原始类型或无效)的 Class ,作为 String 。  
    
        Class<PersonTwo> personClass = PersonTwo.class;
        String name = personClass.getName();
        System.out.println(name);
    
案例
           /*
               需求:写一个"框架",可以帮我们创建任意类的对象,并且执行其中任意方法
               实现:1、配置文件;2、反射
               步骤:1、将需要创建的对象的全类名和需要执行的方法定义在配置文件中
                    2、在程序中加载读取配置文件
                    3、使用反射技术加载类文件进内存
                    4、创建对象
                    5、执行方法
           */
        // 1.加载配置文件
        // 1.1 创建properties对象
        Properties pro = new Properties();
        // 1.2 加载配置文件,转为一个集合
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("properties.properties");
        pro.load(resourceAsStream);
        // 2.获取配置文件中的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");
        // 3.加载该类进内存,
        Class cls=Class.forName(className);
        System.out.println(cls);
        // 4.创建对象
        Constructor constructor = cls.getConstructor(String.class);
        System.out.println(constructor);
        Object obj = constructor.newInstance(className);
        // 5.获取方法对象
        Method method = cls.getMethod(methodName);
        // 6.执行方法
        method.invoke(obj);
package cn.reflecttest;
// 学生类文件
public class Student {
    private String name;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }



    public void sleep(){
        System.out.println("sleeping....");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}
package cn.reflecttest;
// 工人类文件
public class Worker {
    private String name;

    public Worker() {
    }

    public Worker(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "name='" + name + '\'' +
                '}';
    }

    public void work(){
        System.out.println("working....");
    }
}
// .properties配置文件
className=cn.reflecttest.Worker
methodName=work
发布了113 篇原创文章 · 获赞 1 · 访问量 946

猜你喜欢

转载自blog.csdn.net/weixin_44876003/article/details/103385422