初识Java反射机制
最近学到了Java的反射机制,现在对这部分内容做一个总结:
1. Java反射的概念
在Java运行时动态地获取任意一个类的信息,动态地调用任意对象的方法,这就是Java的反射机制。
2. 反射的优缺点
优点:对于Java这种静态语言,它使得Java代码更加灵活(灵活性);
缺点:性能较差(比起直接创建对象进行操作时间上要慢一两个数量级)
3. 实现反射的类
a. Class类:代表正在运行的类。
b. Field类:提供类的成员变量信息,就是类的属性。
c. Method类:提供类的方法信息。
d. Constructor类:提供类的构造方法信息。
3.1 Class类介绍
3.1.1 Class类对象的获取
获取Class对象的方法有三种,现在逐一对它们进行介绍:
1 // 第一种方式就是已知的对象,通过对象.getClass()方法来实现 2 Class class1 = object.getClass(); 3 /*第二种方式就是通过类名.class(类似于调用静态变量,实际不存在class这个变量) 4 假设存在一个动物类Anaimal*/ 5 Class class2 = Animal.class; 6 /*第三种方式就是调用Class类的静态方法forName() 7 此方法使用时会抛出异常(ClassNotFoundException),需要处理 8 类的全称 = 包名 + 类名*/ 9 try{ 10 Class class3 = Class.forName("类的全称"); 11 }catch(ClassNotFoundException c){ 12 c.printStackTrace(); 13 }
3.1.2 Class类中常用方法
getFields()方法和getDeclaredFields()方法,返回值是一个Field类型的数组。
1 Class class1 = ArrayList.class; 2 Field[] fl = class1.getDeclaredFields(); 3 for(Field f:fl){ 4 System.out.println(f.getName()); 5 } 6 /* 7 输出结果为: 8 serialVersionUID 9 elementData 10 size 11 MAX_ARRAY_SIZE 12 */
1 Class class1 = ArrayList.class; 2 Field[] f2 = class1.getFields(); 3 for(Field l:f2){ 4 System.out.println(l.getName()); 5 } 6 /* 7 输出结果为空 8 */
由代码可以看出两个方法都是获取类的属性,但得到的结果不同,那原因是什么呢?我们查询API文档即可得到答案:getFields()方法获得是此 Class 对象所表示的类或接口的所有可访问公共字段,而getDeclaredField()方法获得的是此 Class 对象所表示的类或接口所声明的所有字段(包括私有的,公共的,受保护的)。由代码结果还可以看出,通过类名.class方式获取类对象,并不能说明该类中就有静态变量class,所以我们只能说类似于调用静态变量的方式去获取。
getfiled(String name)和getDeclaredField(String name),返回值是一个由name指定的Field对象。调用该方法时可能会抛出NoSuchFieldException异常,需要进行处理。
public static void main(String[] args)throws NoSuchFieldException{ Class class1 = ArrayList.class; Field fl = class1.getDeclaredField("size"); System.out.println(fl); } /* 输出结果为 private int java.util.ArrayList.size */ public static void main(String[] args)throws NoSuchFieldException{ Class class1 = ArrayList.class; Field fl = class1.getField("size"); System.out.println(fl); } /* 输出结果为: 抛出NoSuchFieldException信息 */
提示:Class类中调用类的构造方法的方法,调用类的方法的方法与调用属性的方法使用相同,大家可自行验证(碍于篇幅限制,就不一一说明了)!
接下来认识Class类中另一个重要方法,Class.newInstance(),作用是创建此 Class 对象所表示的类的一个新实例,返回值是一个对象。
1 Object obj = Class.newInstance();
3.2 Field类的介绍
Field
提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
3.2.1 Field类的常用方法
getName()和getType()两个方法,前者返回的是此 Field
对象表示的字段的名称,后者返回的是一个 Class
对象,它标识了此 Field
对象所表示字段的声明类型。
1 Class class1 = ArrayList.class; 2 Field fl = class1.getDeclaredField("size"); 3 System.out.println("size属性的名字是:"+fl.getName()+"类型是:"+fl.getType()); 4 5 /* 6 输出结果: 7 size属性的名字是:size类型是:int 8 */
3.3 Method类的介绍
Method类提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
3.3.1 Method类常用方法
invoke(Object obj,Object...args)使用参数args在obj上指派该对象所表示的方法,返回值是一个Object对象,是obj上所指派对象所表示方法的运行结果。
public static void main(String[] args)throws Exception{ Class class1 = ArrayList.class; Object obj = class1.newInstance(); Method m = class1.getMethod("add",new Class[]{Object.class}); Object va = m.invoke(obj,new Object[]{5}); System.out.println(va); } /* 输出结果: true */
3.4 Constructor类的介绍
Constructor类提供关于类的单个构造方法的信息以及对它的访问权限。
3.4.1 Constructor类常用的方法
newIntance(object...initargs)方法, 使用此 Constructor
对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
1 Class class1 = object.getClass(); 2 Constructor con = class1.getConstructor(new Class[]{}); 3 Object copy = con.newInstance(new Object[]{});
到这里,Java反射的一些常用知识,我们就了解,但是想要真正掌握它,离不了多动手练习。为了方便记忆,我将知识进行了梳理,做成了思维导图的形式,方便记忆。