欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 反射 - 在运行时分析对象

程序员文章站 2024-01-20 11:56:16
...

Java 反射 - 在运行时分析对象

获取值

先看一段获取字段信息的代码:

var harry = new Employee("harry hacker", 50000);
Class cl = harry.getClass();
Field f = cl.getDeclaredField("name");
Object obj = f.get(harry); 

// 个人理解: 通常访问一个字段, 要求从一个具体的对象出发; 
// 而现在从类出发, 先获取类对象, 然后获取我们想要获取的字段(在类中的位置), 然后在传入对象来获取.
// 这个过程中, 对象处于一个被动的位置, 因为它作为参数被传递给了一个具体的字段的对象. (这就是为什么这个动态获取类信息, 对象信息的过程叫做反射吗?)

获取字段步骤:

  1. 获取目标对象 var harry = ...
  2. 通过对象对象得到对应类 Class cl = harry.getClass()
  3. 通过该类获得目标字段的对象 Field f = cl.getDeclareField("name")
  4. 将目标对象作为你参数传给目标字段对象的 get 方法 Object name = f.get(harry)

权限问题

如果一个字段是私有的, 那么我们用该字段的对象的 setAccessiable() 方法获取访问权限.

f.setAccessible(true); //Field f

如果不允许访问, 就会抛出一个异常.

设置值

使用 set(obj, val) 方法.

f.set(harry, "neo");

实战: 通用的 toString() 方法

返回 json 格式的字符串. (遇到ArrayList等容器类型时还有问题)

package july15;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MyObjectAnalyzer {

    public static String toString(Object obj) throws IllegalAccessException {
        if (obj==null) return "null";
        if (obj instanceof List || obj instanceof Map)
            return obj.toString();
        Class cl = obj.getClass();
        if (cl.isArray()) {
            String r = "[";
            for (int i=0; i<Array.getLength(obj); i++) {
                if (i>0)
                    r += ", ";
                if (Array.get(obj, i)==null)
                    r += "null";
                else
                    r += toString(Array.get(obj, i));
            }
            return r+"]";
        }

        String r = "{";
        Field[] fields = cl.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        for (int i=0; i<fields.length; i++) {
            if (i>0)
                r +=", ";
            r += fields[i].getName()+": ";
            Class eClass = fields[i].getType();
            if (eClass.isArray())
                r += toString(fields[i].get(obj));
            else if (eClass==String.class) {
                r += "\""+fields[i].get(obj)+"\"";
            }
            else if (eClass.isPrimitive())
                r += fields[i].get(obj);
            else {
                r += toString(fields[i].get(obj));
            }
        }

        return r+"}";
    }
}