通过java反射机制获取类的所有属性类型、值

通过需要决定使用  getFields 还是 getDeclaredFields

方法功能
getFields()获取所有public字段,包括父类字段
getDeclaredFields()获取所有字段,public和protected和private,但是不包括父类字段

获取单个:

   /**
     * 根据属性名获取属性值
     *
     * @param fieldName
     * @param object
     * @return
     */

    protected String getFieldValueByFieldName(String fieldName, Object object) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            //设置对象的访问权限,保证对private的属性的访问
            field.setAccessible(true);
            return (String) field.get(object);
        } catch (Exception e) {
            return null;
        }
    }

 获取全部:

  /**
     * 得到属性值
     * @param obj
     */
    public static void readAttributeValue(Object obj) {
        String nameVlues = "";
        //得到class
        Class cls = obj.getClass();
        //得到所有属性
        Field[] fields = cls.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {//遍历
            try {
                //得到属性
                Field field = fields[i];
                //打开私有访问
                field.setAccessible(true);
                //获取属性
                String name = field.getName();
                //获取属性值
                Object value = field.get(obj);
                //一个个赋值
                nameVlues += field.getName() + ":" + value + ",";
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //获取最后一个逗号的位置
        int lastIndex = nameVlues.lastIndexOf(",");

        //不要最后一个逗号","
        String result = nameVlues.substring(0, lastIndex);
        System.out.println(result);
    }

当然,上面的是简单的做法,主要针对String,也可以对Field进行区分

    public void doField(Object object, Field field) throws InvocationTargetException, IllegalAccessException {
        // 如果类型是String
        if (field.getGenericType().toString().equals(
                "class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名
            // 拿到该属性的gettet方法
            /**
             * 这里需要说明一下:他是根据拼凑的字符来找你写的getter方法的
             * 在Boolean值的时候是isXXX(默认使用ide生成getter的都是isXXX)
             * 如果出现NoSuchMethod异常 就说明它找不到那个gettet方法 需要做个规范
             */
            Method m = (Method) object.getClass().getMethod(
                    "get" + getMethodName(field.getName()));

            String val = (String) m.invoke(object);// 调用getter方法获取属性值
            if (val != null) {
                System.out.println("String type:" + val);
            }
        }

        // 如果类型是Integer
        if (field.getGenericType().toString().equals(
                "class java.lang.Integer")) {
            Method m = (Method) object.getClass().getMethod(
                    "get" + getMethodName(field.getName()));
            Integer val = (Integer) m.invoke(object);
            if (val != null) {
                System.out.println("Integer type:" + val);
            }
        }

        // 如果类型是Double
        if (field.getGenericType().toString().equals(
                "class java.lang.Double")) {
            Method m = (Method) object.getClass().getMethod(
                    "get" + getMethodName(field.getName()));
            Double val = (Double) m.invoke(object);
            if (val != null) {
                System.out.println("Double type:" + val);
            }
        }

        // 如果类型是Boolean 是封装类
        if (field.getGenericType().toString().equals(
                "class java.lang.Boolean")) {
            Method m = (Method) object.getClass().getMethod(
                    field.getName());
            Boolean val = (Boolean) m.invoke(object);
            if (val != null) {
                System.out.println("Boolean type:" + val);
            }
        }

        // 如果类型是boolean 基本数据类型不一样 这里有点说名如果定义名是 isXXX的 那就全都是isXXX的
        // 反射找不到getter的具体名
        if (field.getGenericType().toString().equals("boolean")) {
            Method m = (Method) object.getClass().getMethod(
                    field.getName());
            Boolean val = (Boolean) m.invoke(object);
            if (val != null) {
                System.out.println("boolean type:" + val);
            }
        }
        // 如果类型是Date
        if (field.getGenericType().toString().equals(
                "class java.util.Date")) {
            Method m = (Method) object.getClass().getMethod(
                    "get" + getMethodName(field.getName()));
            Date val = (Date) m.invoke(object);
            if (val != null) {
                System.out.println("Date type:" + val);
            }
        }
        // 如果类型是Short
        if (field.getGenericType().toString().equals(
                "class java.lang.Short")) {
            Method m = (Method) object.getClass().getMethod(
                    "get" + getMethodName(field.getName()));
            Short val = (Short) m.invoke(object);
            if (val != null) {
                System.out.println("Short type:" + val);
            }
        }
        // 如果还需要其他的类型请自己做扩展
    }

    // 把一个字符串的第一个字母大写、效率是最高的、
    private static String getMethodName(String fildeName) throws Exception{
        byte[] items = fildeName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }

注意!

通过反射获取信息时,在父类字段为protected时,子类也可以访问的,但无法反射到

例如: A extends B ,那只能反射到A中的属性,无法拿到B当中的。

针对这种情况,可以进行递归父类去getDeclaredFields()

    List<Field> fieldList = new ArrayList<>() ;
    Class tempClass;
    public void getFields(Object object){
        tempClass = object.getClass();

        while (tempClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(tempClass .getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
        }

        for (Field f : fieldList) {
            Log.d("getAllFields","getFields---"+f.getName());
        }
    }

可以看到我们获取了Model和ParentModel的全部字段,不仅如此,还多出来了两个字段 shadow$_klass_shadow_monitor_,这个是Object中的字段.

shadow$_monitor_和shadow$_klass_是Android sdk21之后Object增加的两个字段。

如果你想屏蔽Object类的影响,可以为while循环再添加一个条件:

while (tmpClass !=null && !tmpClass.getName().toLowerCase().equals("java.lang.object") )
{
      ....
}

记得控制一下父类的级别层次,很多时候我们并不需要object 的属性

 

参考:

https://blog.csdn.net/qq_32452623/article/details/54025185

  • 1
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值