javaDEMO
Java 基础 Demo 站: https://www.javastudy.cloud
Java 中高级开发博客: https://www.lixiang.red
Java 学习公众号: java 技术大本营
反射总述
反射通俗来说,可以通过.class 获取到类的描述信息,如这个类中有哪些方法,有哪些属性, 这些方法的入参/返回值是什么, 属性的类型是什么. 常用于各个工具类之中,也是各个框架的底层.我们平时的开发中一个类有: 类(Class), 类属性(Field),方法(Method),方法入参(Parameter),方法返回值(Return)这些东西. 反射的开始是从.class 开始的,如下所示
public void getClassInfo(Class<?> clazz){ // 获取这个类中所有的属性信息 Field[] declaredFields = clazz.getDeclaredFields(); // 获取这个类中所有的方法 Method[] declaredMethods = clazz.getDeclaredMethods(); }
以上述方法为开始,然后拿到我们想要的属性/方法,然后开始我们自己的逻辑
获取实体类的属性值
实体类中有基础属性值,有引用属性值,对于引用属性的,还需要进一步的递归反射去获取相应的属性信息,直至处理到基础性值.但遇到自己引用自己的,要注意停止递归,不然就 StackOverFlow 了
工具类代码如下:
public static Map<String,List<String>> getModelFields(Class<?> clazz){ // 选用linkedHashMap是为了有序,存复杂类型映射的结果 // key-value: com.xxx.xxx.xx <-> ["int-bName","Integer-testInter"] Map<String, List<String>> exitsMap = new LinkedHashMap<>(); doGetModelFields(clazz,exitsMap); return exitsMap; } public static void doGetModelFields(Class<?> clazz,Map<String,List<String>> map){ String clazzName = clazz.getCanonicalName(); // 为了防止循环引用,先加入到map中 List<String> list = new ArrayList<>(); map.put(clazzName,list); // 这个方法只能获取到自己类中的Field,不包含父类的 // 要注意有个this Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String fieldName = field.getName(); if(fieldName.contains("this")){ continue; } Class<?> fieldType = field.getType(); String fullName = fieldType.getCanonicalName(); String simpleName = fieldType.getSimpleName(); list.add(simpleName+"-"+fieldName); if(!simpleClass(fieldType)){ // 判断这个是不是基础属性,如果是的话,则可以结束了 // 这里获取到的name是 com.platform.xxx.xxx.Model 这样的全路径 //如果是复杂属性的话,则先看map中有没有这个属性 if(!map.containsKey(fullName)){ // 递归去获取属性值 doGetModelFields(fieldType,map); } } } } /** * 判断这个类是否是基础类型 * @param parameterType * @return */ public static boolean simpleClass(Class<?> parameterType) { return parameterType == String.class || parameterType == Integer.class || parameterType == int.class|| parameterType == Double.class || parameterType == double.class || parameterType == Long.class || parameterType == long.class || parameterType == Float.class || parameterType == float.class || parameterType == Byte.class || parameterType == byte.class; }
测试工具类
这里我们写子两个类,A,B,C 有基础属性,有引用属性,有循环引用来做测试
public static void main(String[] args) { // 把A传进去做测试 Map<String, List<String>> modelFields = getModelFields(A.class); System.out.println(modelFields); } class A { private String aName; private String aCCC; private B b; } class B { private A a; private C c; private String bName; } class C { private String cName; }
得到的结果如下,可以看到这个 A 这个实体类的中属性都已经到 Map 中了
DEMO 总评
反射是很多工具类/框架的基础,熟练的掌握反射的开发,能为平时开发省不少时间,如我们可以用反射给应用开个后门,直接通过一个 Controller 调用所有的 Bean 来测试,如加载.class 再配合一些注解生成接口文档,如以前写的工具:Excel 和 List 互转也用到了反射,从 List 中根据某一属性查询也用到了反射,加油吧!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于