反射

反射:框架设计的灵魂

名词解释:
    * 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
    * 反射:将类的各个组成部分封装为其他对象,这就是反射机制        
使用反射优点:
        1. 可以在程序运行过程中,操作这些对象。
        2. 可以解耦,提高程序的可扩展性。

获取Class对象的方式

1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
      * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2. 类名.class:通过类名的属性class获取
      * 多用于参数的传递
3. 对象.getClass():getClass()方法在Object类中定义着。
      * 多用于对象的获取字节码的方式

三种方式获取Class对象代码

 1 package demo14.reflect;
 2 
 3 public class demo01 {
 4     public static void main(String[] args) throws ClassNotFoundException {
 5         // 1 Class.forName("全类名")
 6         Class aClass = Class.forName("demo14.reflect.Person");
 7         System.out.println(aClass);
 8 
 9         // 2 类名.class
10         Class bClass = Person.class;
11         System.out.println(bClass);
12 
13         // 3 对象.getClass()
14         Person person = new Person();
15         Class cClass = person.getClass();
16         System.out.println(cClass);
17 
18         //检查三种方式获取的Class对象是否一致
19         System.out.println(aClass == bClass);
20         System.out.println(bClass == cClass);
21         
22     }
23 }

执行结果

# 注:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

 Class对象功能

1. 获取成员变量们
     * Field[] getFields() :获取所有public修饰的成员变量
     * Field getField(String name)   获取指定名称的 public修饰的成员变量

     * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
     * Field getDeclaredField(String name)  
2. 获取构造方法们
     * Constructor<?>[] getConstructors()  
     * Constructor<T> getConstructor(类<?>... parameterTypes)  

     * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)  
     * Constructor<?>[] getDeclaredConstructors()  
3. 获取成员方法们:
     * Method[] getMethods()  
     * Method getMethod(String name, 类<?>... parameterTypes)  

     * Method[] getDeclaredMethods()  
     * Method getDeclaredMethod(String name, 类<?>... parameterTypes)  

4. 获取全类名    
     * String getName()  
Field:成员变量
    * 操作:
       1. 设置值
          * void set(Object obj, Object value)  
       2. 获取值
          * get(Object obj) 
       3. 忽略访问权限修饰符的安全检查
          * setAccessible(true):暴力反射

Constructor:构造方法
    * 创建对象:
        * T newInstance(Object... initargs)  
        * 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

Method:方法对象
     * 执行方法:
        * Object invoke(Object obj, Object... args)  
     * 获取方法名称:
        * String getName:获取方法名

Class对象获取成员变量、对成员变量值进行获取与设置代码示例

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 public class demo02 {
 6     public static void main(String[] args) throws Exception {
 7         /*
 8          * Field[] getFields() :获取所有public修饰的成员变量
 9          * Field getField(String name)   获取指定名称的 public修饰的成员变量
10 
11          * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
12          * Field getDeclaredField(String name)  获取指定名称的成员变量 不考虑修饰符
13          */
14 
15         // 1 获取Class对象
16         Class cls = Class.forName("demo14.reflect.Person");
17 
18         // 2 获取成员变量方法
19         // 2.1 获取所有的public修饰的成员变量
20         Field[] fields = cls.getFields();
21         for (Field field : fields) {
22             System.out.println(field);
23         }
24         // 2.2 获取指定的public修饰的成员变量
25         Field a = cls.getField("a");
26         System.out.println(a);
27         //2.2.1获取和设置Field值
28         Person person = new Person();
29         Object o = a.get(person);
30         System.out.println(o);
31         a.set(person, "kelvin");
32         System.out.println(person);
33 
34         // 2.3 获取所有的成员变量
35         Field[] declaredFields = cls.getDeclaredFields();
36         for (Field field : declaredFields) {
37             System.out.println(field);
38         }
39 
40         // 2.4 获取指定的成员变量
41         Field d = cls.getDeclaredField("d");
42         System.out.println(d);
43         //忽略访问权限修饰符的安全检查(暴力反射)
44         d.setAccessible(true);
45         //2.4.1获取和设置非public修饰的Field值
46         Person person1=new Person();
47         Object o1 = d.get(person1);
48         System.out.println(o1);
49         d.set(person1,"jack");
50         System.out.println(person1);
51     }
52 }

Class对象获取构造方法,并根据构造方法创建对象

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.util.Arrays;
 5 
 6 public class demo03 {
 7     public static void main(String[] args) throws Exception {
 8         /*
 9          Constructor<?>[] getConstructors()
10          Constructor<T> getConstructor(类<?>... parameterTypes)
11 
12          Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
13          Constructor<?>[] getDeclaredConstructors()
14 
15         创建对象:
16         T newInstance(Object... initargs)
17         如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
18 
19          */
20 
21         Class cls = Class.forName("demo14.reflect.Person");
22         // 1 获取所有public修饰的构造方法
23         Constructor[] constructors = cls.getConstructors();
24         System.out.println(Arrays.toString(constructors));
25 
26         // 2 获取指定的参数的构造方法
27         Constructor constructor = cls.getConstructor(String.class, int.class);
28         System.out.println(constructor);
29         // 2.1 使用有参构造方法创建对象
30         Object kelvin = constructor.newInstance("kelvin", 23);
31         System.out.println(kelvin);
32 
33         // 3 获取无参构造方法
34         Constructor constructor1 = cls.getConstructor();
35         System.out.println(constructor1);
36         // 3.1 使用无参构造方法创建对象
37         // 方式一
38         Object o = constructor1.newInstance();
39         System.out.println(o);
40         // 方式二
41         Object o1 = cls.newInstance();
42         System.out.println(o1);
43 
44 
45     }
46 }

Class获取成员方法并执行

 1 package demo14.reflect;
 2 
 3 import java.lang.reflect.Method;
 4 import java.util.Arrays;
 5 
 6 public class demo04 {
 7     public static void main(String[] args) throws Exception {
 8         /*
 9           Method[] getMethods()
10           Method getMethod(String name, 类<?>... parameterTypes)
11 
12           Method[] getDeclaredMethods()
13           Method getDeclaredMethod(String name, 类<?>... parameterTypes)
14 
15           执行方法:
16             Object invoke(Object obj, Object... args)
17           获取方法名称:
18             String getName:获取方法名
19 
20          */
21         Class cls = Class.forName("demo14.reflect.Person");
22 
23         // 1 获取所有的public成员方法
24         Method[] methods = cls.getMethods();
25         System.out.println(Arrays.toString(methods));
26         // 2 获取指定的public成员带参方法
27         Person person = new Person();
28         Method run = cls.getMethod("run", String.class);
29         run.invoke(person, "kelvin");
30         // 3 获取指定的public修饰无参成员方法
31         Method run1 = cls.getMethod("run");
32         run1.invoke(person);
33 
34         // 4 获取private修饰的成员方法
35         Method eat = cls.getDeclaredMethod("eat");
36         // 暴力反射
37         eat.setAccessible(true);
38         eat.invoke(person);
39     }
40 }

反射应用实例

借助配置文件,配置文件可以配置类和方法。

 1 package demo14.reflect;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.lang.reflect.Method;
 6 import java.util.Properties;
 7 
 8 public class demotest {
 9     /*
10     不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
11     */
12     public static void main(String[] args) throws Exception {
13         Properties pro = new Properties();
14 
15         ClassLoader classLoader = demotest.class.getClassLoader();
16         InputStream resourceAsStream = classLoader.getResourceAsStream("demo14/reflect/pro.properties");
17         pro.load(resourceAsStream);
18 
19         String className = pro.getProperty("className");
20         String classMethod = pro.getProperty("classMethod");
21 
22         Class cls = Class.forName(className);
23         Method method = cls.getMethod(classMethod);
24 
25         Object o = cls.newInstance();
26         method.invoke(o);
27     }
28 }

配置文件

className=demo14.reflect.Student
classMethod=study

 反射图解

 

原文地址:https://www.cnblogs.com/sun-10387834/p/13528770.html