反射
概述
JAVA反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法功能称为Java语言的反射机制。
想要解剖一个类,必须先要获取到该类的字节码文件对象。而而解剖使用的就是Class类中的方法,所以现在要获取到每一个字节码文件对应的Class类型的对象。
获取Class对象
通过class.forName()来获取Class对象
1
Class clazz = Class.forName("com.xx.entity.Emp");
通过
类名.class来获取1
Class<Emp> class = Emp.class;
通过对象的
getClass()来获取1
Class<? extends Emp> clazz = new Emp().getClass();
基本数据类型可以通过TYPE的方式获取class
1
Class<Integer> type = Integer.TYPE;
推荐第1、2种方式
Class对象方法
1 | Class<?> clazz = Class.forName("com.xx.xx.类名"); |
getFields()获取成员变量,包括子类、父类,同时只能包含公共的方法
1
2
3
4
5
6
7
8
9
10
11
12Field[] fields = clazz.getFields();
for(Field field: fields) {
// 字段名称
field.getName();
// 字段类型
field.getType();
// 字段修饰符
field.getModifiers();
}getDeclaredFields()获取当前类的所有属性,不仅仅是公共访问修饰符,所有的访问修饰符都可以拿到
1
2
3
4Field[] declaredFields = clazz.getDeclaredFields();
// xx表示该类中的某个字段名
Field xx = clazz.getDeclaredField("xx");为对象设值
假设有一个类
Student,含有私有属性address(用private修饰的字段),正常情况下private修饰的属性无法被外界访问,但是通过反射能够为address字段设值1
2
3
4
5
6
7
8
9
10
11Class clazz = Class.forName("com.xx.entity.Student");
// 获取address字段
Field address = clazz.getDeclaredField("address");
// 将address字段的访问权限设置为可访问,true表示能访问
address.setAccessible(true);
// 为address字段赋值
Object o = clazz.newInstance();
address.set(o, "上海市");反射在一定程度上破坏了封装性,需要合理使用
getMethods()获取对象中的普通方法,包含当前对象和父类对象的公共方法
getDeclaredMethods()获取当前类中的所有方法,包括私有方法
getConstructors()获取对象所有的公有构造方法,不包含父类构造方法
getDeclaredConstructors()获取对象的所有构造方法,包括私有,不包含父类构造方法
1
2
3
4
5
6
7
8Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
// 调用私有的构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
Object o2 = declaredConstructor.newInstance("参数1", 2);