目录
1.什么是反射
反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。
每个.class文件被加载到内存后都是一个Class类的对象!例如Demo.class加载到内存后它是Class<Demo>类型的一个对象。
反射就是通过Class对象获取类型相关的信息。一个Class对象就表示一个.class文件,可以通过Class对象获取这个类的构造器、方法,以及成员变量等。
2. 反射机制的功能
Java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
3. 实现反射机制的类
Java中主要由以下的类来实现Java反射机制(这些类都位于java.lang.reflect包中):
-
Class类:代表一个类。 Field类:代表类的成员变量(成员变量也称为类的属性)。
-
Method类:代表类的方法。
-
Constructor类:代表类的构造方法。
-
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
3.1 获取Class类的三种基本方式
- 类名.class
- 对象.getClass()
- Class.forName(“类的全路径”)
下面列举先类的常用方法,除此之外还有许多方法,可以通过API去查看
3.1.1 Class类的常用方法
- String getName():获取类名称,包含包名;
- String getSimpleName():获取类名称,不包含包名;
- Class getSupperClass():获取父类的Class,例如:new Integer(100).getClass().getSupperClass()返回的是Class<Number>!但new Object().getSupperClass()返回的是null,因为Object没有父类;
- T newInstance():使用本类无参构造器来创建本类对象;
3.1.2 Method常用方法
- String getName():获取方法名;
- Class getDeclaringClass():获取方法所属的类型;
- Class[] getParameterTypes():获取方法的所有参数的类型;
- Class[] getExceptionTypes():获取方法上声明的所有异常类型;
- Class getReturnType():获取方法的返回值类型;
- Object invode(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;
3.1.3Construcator类常用方法
- String getName():获取构造器名;
- Class getDeclaringClass():获取构造器所属的类型;
- Class[] getParameterTypes():获取构造器的所有参数的类型;
- Class[] getExceptionTypes():获取构造器上声明的所有异常类型;
- T newInstance(Object… initargs):通过构造器反射对象调用构造器。
3.1.4Field类的常用方法
- String getName():获取成员变量名;
- Class getDeclaringClass():获取成员变量的类型;
- Class getType():获取当前成员变量的类型;
- Object get(Object obj):获取obj对象的成员变量的值;
- void set(Object obj, Object value):设置obj对象的成员变量值为value;
3.1.5 AccessibleObject
AccessibleObject类是Constructor、Method、Field三个类的父类。AccessibleObject最为重要的方法如下:
- boolean isAccessible():判断当前成员是否可访问;
- void setAccessible(boolean flag):设置当前成员是否可访问。//[当设置该参数为true时,那么private的成员、方法、构造器就都可以操作了。
当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。
4.例子
4.1通过反射判断对象的属性值是否为空
Object object=new Object();
Class<?> clazz=object.getClass();
Field[] fieldList=clazz.getDeclaredFields();
for (Field field:fieldList) {
//获取属性的is和get方法
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
//通过get方法拿到值
Object invoke = pd.getReadMethod().invoke(object);
if(null== invoke){
return true;
}
}
注意: 如果报错“Method not found: isSerialVersionUID”等 找不到方法,请确认是否有is和get方法并符合规范命名,当然也可以选择忽略掉某些属性
if("serialVersionUID".equals(field.getName())){
}
4.2利用反射将 list转换为Map ,k为对象的属性值
//利用反射list转换为map
List<LogicRoomMapperDetail> list = new ArrayList<>();
LogicRoomMapperDetail detail = new LogicRoomMapperDetail();
detail.setSubjectName("这是K");
list.add(detail);
HashMap<Object, Object> destMap = new HashMap<>(list.size());
for (Object object : list) {
PropertyDescriptor pd = new PropertyDescriptor("subjectName",
object.getClass());
Object keyValue = pd.getReadMethod().invoke(object);
destMap.put(keyValue, object);
}
LogicRoomMapperDetail logicRoomMapperDetail = (LogicRoomMapperDetail) destMap.get(detail.getSubjectName());
4.3对象与对象之间的属性值复制
可以看下BeanCopier类的create方法