反射机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射机制相关的知识,希望对你有一定的参考价值。

JAVA反射机制就是在运行状态中,对于任意一个类(class文件),都能知道这个类的所有属性和方法。

对于任意一个对象,都能调用他的任意一个属性和方法。

这种动态获取的信息以及动态调用对象的方法的功能成为java语言的反射机制。

 

简单说:动态获取类中信息,就是反射机制,可以理解为对类的解剖。

 

想要对一个类进行解剖,只要获取到该类的字节码文件对象即可,即  .class文件

获取Class对象的三种方式:

第一种方式:Object类中的getClass()方法

第二种方式:任何数据类型都有一个静态的属性.calss来获取对应的class对象。

第三种方式:Class类中有一个forName()方法,只要给定类的字符串名称就可以获取该类。

 

 1 public static void main(String[] args) throws ClassNotFoundException {
 2             
 3         getClassObject_3();
 4     
 5     }
 6     /*
 7      * 方式三:
 8      * 只要通过给定的类的 字符串名称就可以获取该类,更为扩展。
 9      * 可是用Class类中的方法完成。
10      * 该方法就是forName.
11      * 这种方式只要有名称即可,更为方便,扩展性更强。 
12      */
13     
14     public static void getClassObject_3() throws ClassNotFoundException {
15         
16         String className = "cn.itcast.bean.Person";
17         
18         Class clazz = Class.forName(className);
19         
20         System.out.println(clazz);
21     }
22     
23     
24 
25 
26 
27     /*
28      * 方式二:
29      * 2,任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
30      * 相对简单,但是还是要明确用到类中的静态成员。
31      * 还是不够扩展。 
32      * 
33      */
34     public static void getClassObject_2() {
35         
36         Class clazz = Person.class;
37         
38         Class clazz1 = Person.class;
39         System.out.println(clazz==clazz1);
40     }
41     
42     /*
43      * 获取字节码对象的方式:
44      * 1,Object类中的getClass()方法的。
45      * 想要用这种方式,必须要明确具体的类,并创建对象。
46      * 麻烦 .
47      * 
48      */
49     public static void getClassObject_1(){
50         
51         Person p = new Person();
52         Class clazz = p.getClass();
53         
54         Person p1 = new Person();
55         Class clazz1 = p1.getClass();
56         
57         System.out.println(clazz==clazz1);
58     }

 

如何产生对象:

 

 1 public static void createNewObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
 2         
 3         
 4         //早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,
 5 //        并创建该字节码文件对象,并接着创建该字节文件的对应的Person对象.
 6 //        cn.itcast.bean.Person p = new cn.itcast.bean.Person();
 7         
 8         //现在:
 9         String name = "cn.itcast.bean.Person";
10         //找寻该名称类文件,并加载进内存,并产生Class对象。
11         Class clazz = Class.forName(name);
12         //如何产生该类的对象呢?
13         Object obj  = clazz.newInstance();
14         
15         
16         
17         
18     }

 

获取构造函数:

 1 public static void createNewObject_2() throws Exception {
 2         
 3 //        cn.itcast.bean.Person p = new cn.itcast.bean.Person("小强",39);
 4         
 5         /*
 6          * 当获取指定名称对应类中的所体现的对象时,
 7          * 而该对象初始化不使用空参数构造该怎么办呢?
 8          * 既然是通过指定的构造 函数进行对象的初始化,
 9          * 所以应该先获取到该构造函数。 通过字节码文件对象即可完成。
10          * 该方法是:getConstructor(paramterTypes);
11          * 
12          */
13         String name = "cn.itcast.bean.Person";
14         //找寻该名称类文件,并加载进内存,并产生Class对象。
15         Class clazz = Class.forName(name);
16         //获取到了指定的构造函数对  象。
17         Constructor constructor = clazz.getConstructor(String.class,int.class);
18         
19         //通过该构造器对象的newInstance方法进行对象的初始化。
20         Object obj = constructor.newInstance("小明",38);
21         
22             
23         
24     }

 

获取字段:

 1 /*
 2      * 获取字节码文件中的字段。
 3      */
 4     public static void getFieldDemo() throws Exception {
 5         
 6         Class clazz = Class.forName("cn.itcast.bean.Person");
 7         
 8         Field field = null;//clazz.getField("age");//只能获取公有的,
 9         
10         field = clazz.getDeclaredField("age");//只获取本类,但包含私有。 
11         
12         //对私有字段的访问取消权限检查。暴力访问。
13         field.setAccessible(true);
14         
15         Object obj = clazz.newInstance();
16         
17         field.set(obj, 89);//要先有对象才能设置字段值,所以要先创建实例才能设置字段值。
18         
19         
20         Object o = field.get(obj);
21         
22         System.out.println(o);
23         
24 //        cn.itcast.bean.Person p = new cn.itcast.bean.Person();
25 //        p.age = 30;
26         
27     }

 

获取Class中的方法:

/*
     * 获取指定Class中的所有公共函数。
     */
    public static void getMethodDemo() throws Exception {
        
        Class clazz = Class.forName("cn.itcast.bean.Person");
        
        Method[] methods  = clazz.getMethods();//获取的都是公有的方法。 
        methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。 
        for(Method method : methods){
            System.out.println(method);
        }
        
        
    }

 

获取方法的时候必须指定方法名即参数列表。

 

//获取空参数的方法

 1 public static void getMethodDemo_2() throws Exception {
 2         
 3         Class clazz = Class.forName("cn.itcast.bean.Person");
 4         
 5         Method method = clazz.getMethod("show", null);//获取空参数一般方法。
 6         
 7 //        Object obj = clazz.newInstance();空参构造函
8 Constructor constructor = clazz.getConstructor(String.class,int.class); 9 Object obj = constructor.newInstance("小明",37); 10 11 //方法运行必须有对象,对象必须指定用哪个构造函数来创建。 12 method.invoke(obj, null); 13 14 15 16 }

 

有参数列表的方法:

 1 public static void getMethodDemo_3() throws Exception {
 2         
 3         Class clazz = Class.forName("cn.itcast.bean.Person");
 4         
 5         Method method = clazz.getMethod("paramMethod", String.class,int.class);
 6         
 7         Object obj = clazz.newInstance();
 8         
 9         method.invoke(obj, "小强",89);
10         
11         
12     }

 

以上是关于反射机制的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

java 反射代码片段

python反射机制实现

Java核心技术梳理-类加载机制与反射

Java反射机制