java 基础 | 通过反射获取实体类属性

本贴最后更新于 1559 天前,其中的信息可能已经时异事殊

javaDEMO

Java 基础 Demo 站: https://www.javastudy.cloud
Java 中高级开发博客: https://www.lixiang.red
Java 学习公众号: java 技术大本营
java_subscribe

反射总述

反射通俗来说,可以通过.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 中了
image.png

DEMO 总评

反射是很多工具类/框架的基础,熟练的掌握反射的开发,能为平时开发省不少时间,如我们可以用反射给应用开个后门,直接通过一个 Controller 调用所有的 Bean 来测试,如加载.class 再配合一些注解生成接口文档,如以前写的工具:Excel 和 List 互转也用到了反射,从 List 中根据某一属性查询也用到了反射,加油吧!

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...