Java正射,即为通过实例对象访问class对象;Java反射,即是通过class访问对象的属性和方法。
本篇文章,是反射的第一部分,笔者主要分享如下内容:
- 反射获取本类的私有属性
- 反射获取父类的私有属性
- 反射获取本类中非基本类型的私有属性
- 反射获取泛型类的私有属性
- 反射获取内部类的私有属性
接下来,我们详细介绍每个部分的内容:
反射获取本类的私有属性
用户类User是我们此次研究的主要对象,根据不同的场景,我们将其命名为User1,User2,User3...
根据本次场景,User1是单独的类,相关代码如下:
import lombok.Data; @Data public class User1 { private Long id; private String name; private String descr; }
其访问测试方法如下:
import lombok.extern.slf4j.Slf4j; import java.lang.reflect.Field; @Slf4j public class ReflectClass { public void reflectClass(Object object,Class clazz){ try { for (Field field:clazz.getDeclaredFields()){ //设置可访问属性 field.setAccessible(true); Object fieldValue = field.get(object); log.info("fieldName:{},fieldValue:{}",field.getName(),fieldValue); } }catch (Exception e){ e.printStackTrace(); } } public static void main(String[] args) { User1 user1 = new User1(); user1.setId(1L); user1.setName("perry"); user1.setDescr("描述"); ReflectClass reflectClass = new ReflectClass(); reflectClass.reflectClass(user1, User1.class); } }
在测试方法中,`clazz.getDeclaredFields()` 获取该类的所有声明的属性,包括public,private,protected等等.如果仅仅需要访问private属性,
可以通过`field.getModifiers()`,进行区分,private在该方法下值为2,public为1,protected为4,static为8,final为16,synchronized为32,volatile为64,transient为128。
接下来,进入下个专题:
反射获取父类的私有属性
我们常常会将很多实体类继承一个基类,基类保存相关审计字段,比如createDate,createUser,updateDate,updateUser.
import lombok.Data; import java.util.Date; @Data public class BaseObject { private Date createDate; private Date updateDate; private String createUser; private String updateUser; }
User类修改如下,
import lombok.Data; @Data public class User2 extends BaseObject{ private Long id; private String name; private String descr; }
其实现方法如下:
public void reflectSuperClass(Object object,Class clazz){ try { clazz = clazz.getSuperclass(); if (clazz != null){ reflectClass(object,clazz); } }catch (Exception e){ e.printStackTrace(); } }
反射获取本类中非基本类型的私有属性
本次,我们重构下之前的reflectClass()方法,如果其属性不是基本类型,则递归获取其值
本场景下,用户持有Department属性,相实体对象如下:
import lombok.Data; @Data public class Department { private Long id; private Long pid; private String name; private String descr; }
用户类如下:
import lombok.Data; @Data public class User3 { private Long id; private String name; private String descr; private Department department; }
其实现访问类如下:
public void reflectClass(Object object,Class clazz){ try { for (Field field:clazz.getDeclaredFields()){ //设置可访问属性 field.setAccessible(true); // log.info("modifier:{}",field.getModifiers()); Object fieldValue = field.get(object); if (fieldValue != null && !isBaseType(fieldValue)){ reflectClass(fieldValue,fieldValue.getClass()); } log.info("fieldName:{},fieldValue:{}",field.getName(),fieldValue); } }catch (Exception e){ e.printStackTrace(); } } private boolean isBaseType(Object object) { if (object instanceof String || object instanceof Boolean || object instanceof Integer || object instanceof Double || object instanceof Date) { return true; } return false; }
反射获取泛型类的私有属性
实现同 获取本类中非基本类型的私有属性。只不过其用户类定义如下:
import lombok.Data; @Data public class User4<T> { private Long id; private String name; private String descr; private T data; }
测试方法如下:
private static void testUser4(){ log.info("test 反射获取泛型类的私有属性 start .."); User4<Department> user4 = new User4<>(); user4.setName("perry"); Department department = new Department(); department.setName("技术部"); user4.setData(department); ReflectClass reflectClass = new ReflectClass(); reflectClass.reflectClass(user4, User4.class); log.info("test 反射获取泛型类的私有属性 end .."); }
反射获取内部类的私有属性
内部类获取属性的方法,同获取本类中私有属性的方法。只不过测试方式上有区别:
因为内部类存在下列特征:
1. 在内部类中可以随意使用外部类的成员方法以及成员变量。
2.要在外部类中实例化内部类对象的引用。
3.使用this关键字获取内部类与外部类对象的引用。
也就是说,调用的时候,传递的时内部类的对象,而非外部类对象,如果是外部类对象,它就找不到内部类对象了。
该场景下用户类如下声明:
import lombok.Data; @Data public class User5 { private Long id; private String name; private String descr; @Data class Role { private String roleName; } }
其测试方法如下:
private static void testUser5(){ log.info("test 反射获取内部类的私有属性 start .."); User5 user5 = new User5(); user5.setName("perry"); //内部类 User5.Role role = user5.new Role(); role.setRoleName("管理员"); ReflectClass reflectClass = new ReflectClass(); //注意调用对象 reflectClass.reflectClassWithInnderClass(role, User5.Role.class); log.info("test 反射获取内部类的私有属性 end .."); }
以上介绍了关于反射的一些场景,以及一些通用的获取属性的方法,相关代码比较详细。
如有需要全部代码,可与我留言。