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 中根据某一属性查询也用到了反射,加油吧!
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于