30.2 Java进阶之反射查看属性的值,查看任意对象的内部信息


总结自《Java核心技术卷Ⅰ》

1.通过反射机制查看对象属性的值

利用反射机制可以查看在编译时还不清楚的对象域,就是具体运行时才能获取到的属性的值。
可以再程序运行时获取对象属性值,其中的关键是Field类中的get方法。

如果field是一个Field类型的对象,obj是某个包含field的类的对象,则field.get(obj)将返回一个对象,其就是obj名为field.getName()的属性的当前值。
除此之外我们还可以调用field.set(obj,value);将obj对象的名为field.getName()的属性设置成新值。

1.1 实例演示

1.1.1.Employee.java

public class Employee {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public Employee(String name) {
        this.name=name;
    }
}

1.1.2 ReflectionTest.java

import java.lang.reflect.Field;

public class ReflectionTest {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Employee harry = new Employee("Harry Hacker");
        Class cl=harry.getClass();
        Field f = cl.getDeclaredField("name");
        //必须有,否则无法访问name的值会出错,作用是将所有域设置成可访问的
        f.setAccessible(true);
        Object v = f.get(harry);
        //输出的是Harry Hacker
        System.out.println(v);
        f.set(harry,"牧之");
        System.out.println(f.get(harry));
    }
}

在这里插入图片描述

2.编写toString方法来查看任意对象内部信息

通过上面的学习,我们可以使用反射机制来写出通用的toString程序来打印出任意对象的所有的属性值信息。
在学习例子之前我们应先了解相关方法:
在这里插入图片描述

//此方法能获取当前类的父类的Class,可以用于访问定义在父类的属性
public native Class<? super T> getSuperclass();

2.1 ObjectAnalyzer.java

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

public class ObjectAnalyzer{

    private ArrayList<Object> visited = new ArrayList<>();

    /**
     * 此方法利用放射将传入的对象toString化
     * @param obj
     * @return String
     */
    public String toString(Object obj){
        //首先判断传入的对象是否空对象,如果是直接返回null
        if (obj == null) return "null";
        //然后判断是否已经传入过相同的对象进来,如果是,返回 ...
        if (visited.contains(obj)) return "...";
        //将obj对象加入全局变量visited中
        visited.add(obj);
        //获得传入对象的class实例
        Class<?> cl = obj.getClass();
        //判断传入的对象是否是字符串对象,如果是,强转后直接返回
        if (cl == String.class){
            return (String) obj;
        }
        //基本数据类型直接返回其对应的基本类型数值描述
//        if(cl==Integer.class||cl==Double.class||cl==Short.class||cl==Byte.class||cl==Float.class||cl==Long.class||cl==Boolean.class||cl==Character.class){
//            return obj.toString();
//        }
        //如果是数组类型,则
        if (cl.isArray()) {
            String r = cl.getComponentType() + "[]{";

            for (int i = 0; i < Array.getLength(obj); i++) {
                if (i > 0){
                    r += ",";
                }
                //获得数组指定位置的元素
                Object val = Array.get(obj, i);
                //判断元素是不是基本类型
                if (cl.getComponentType().isPrimitive()) {
                    r += val;
                } else {
                    r += toString(val);
                }
            }
            System.out.println(r);
            return r + "}";
        }

        String r = cl.getName();

        //将传入对象String化
        do {
            r += "[";
            Field[] fields = cl.getDeclaredFields();
            //这个操作可以让反射机制对私有属性也能进行操作
            AccessibleObject.setAccessible(fields, true);
            for (Field f : fields) {
                if (!Modifier.isStatic(f.getModifiers())) {
                    if (!r.endsWith("[")) r += ",";
                    r += f.getName() + "=";
                    try {
                        Class t = f.getType();
                        Object val = f.get(obj);
                        //判断属性是不是基本类型
                        if (t.isPrimitive()) {
                            r += val;
                        }
                        else r += toString(val);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            r += "]";
            //获得此类的父类型Class
            cl = cl.getSuperclass();
        } while (cl != null);

        return r;
    }
}

2.2 ToStringTest.java

public static void main(String[] args) {
    Integer squares=new Integer(20);
    System.out.println( new ObjectAnalyzer().toString(squares));
}

在这里插入图片描述

3.代码仓库地址

Java基础学习/src/main/java/Progress/exa30_2 · 严家豆/Study - 码云 - 开源中国 (gitee.com)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小牧之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值