如何使用反射获取对象字段的对象引用?

时间:2014-02-14 15:16:53

标签: java object reflection

注意:每次我去打字这个问题,我想我会看到一些东西,但它永远不会播出,所以第三次或第四次。

概要:我正在尝试使用Response类序列化从基本Response类继承的对象,其子类可能具有非原始字段类型。

代码是这样的(警告:大而不优雅),从特定类(SpecificResponse)排序,从公共类扩展(CommonResponse),这是抽象类(Response)的具体实现,驱动通过测试程序(程序)。

// SpecificResponse.java
package com.jdgj.thinking;

public final class SpecificResponse extends CommonResponse {
    public String hell;
    public int trike;
    public short tail;
    public SpecificResponse() {
        super();
    }
}

specificationcResponse扩展了CommonResponse:

// CommonResponse.java
package com.jdgj.thinking;

public class CommonResponse extends Response {
    public int thing2;
    public Value value;
    @Override
    protected void initialize() {
        System.out.println("hello!");
        value = new Value();
    }
}

出于测试目的,我只创建了一个简单的Value对象:

// Value.java
package com.jdgj.thinking;

public class Value {
    public int five;
}

而且,它做了很多工作,也是CommonResponse的基础,Response类:

// Response.java
package com.jdgj.thinking;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public abstract class Response {
    public static Class<?> fromClassSignature(List<String> signature) throws IllegalArgumentException, IllegalStateException, ClassNotFoundException {
        if (signature == null || signature.size() == 0) {
            throw new IllegalArgumentException("Null or empty Response class signature.");
        }
        String lastClassName = null;
        for (String line : signature) {
            if (line.startsWith("class:")) {
                lastClassName = line.split(":")[1];
            }
        }
        if (lastClassName == null) {
            throw new IllegalStateException("Could not find the Response class name.");
        }
        Class<?> c = Class.forName(lastClassName);
        lastClassName = null;
        Class<?> sc = c.getSuperclass();
        while (sc != null && !sc.equals(Response.class)) {
            sc = sc.getSuperclass();
        }
        if (sc != null) {
            sc = null;
            return c;
        } else {
            return null;
        }
    }
    protected abstract void initialize();
    private String getFieldSignature(Field field) {
        return "field:" + field.getName() + "|" + field.getType().getCanonicalName();
    }
    private List<String> serializeObject(Class<?> c, Object o) {
        List<String> serialization = new ArrayList<String>(0);
        serialization.add("class:" + c.getName());
        for (Field f : c.getDeclaredFields()) {
            if (!f.isSynthetic() && Modifier.isPublic(f.getModifiers())) {
                StringBuilder sb = new StringBuilder(getFieldSignature(f));
                Class<?> t = f.getType();
                Object value = null;
                try {
                    value = f.get(o);
                    System.out.println(f.getName() + "=" + value);
                    if (t.isPrimitive() || t.equals(String.class)) {
                        sb.append("`" +  value.toString() + "");
                    }
                } catch (NullPointerException e) {
                    if (t.isPrimitive() || t.equals(String.class)) {
                        sb.append("`");
                    } else {
                        System.out.println("UNEXPECTED NULL POINTER EXCEPTION");
                    }
                } catch (IllegalArgumentException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IllegalAccessException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } finally {
                    serialization.add(sb.toString());
                    if (value != null) {
                        if (!(t.isPrimitive() || t.equals(String.class))) {
                            serialization.addAll(serializeObject(t, value));
                        }
                    }
                }
                sb = null;
                t = null;
            }
        }
        return serialization;
    }
    private List<String> describeClass(Class<?> c) {
        List<String> description = new ArrayList<String>(0);
        description.add("class:" + c.getName());
        for (Field f : c.getDeclaredFields()) {
            if (!f.isSynthetic() && Modifier.isPublic(f.getModifiers())) {
                description.add(getFieldSignature(f));
                Class<?> t = f.getType();
                if (!(t.isPrimitive() || t.equals(String.class))) {
                    description.addAll(describeClass(t));
                }
                t = null;
            }
        }
        return description;
    }
    public final List<String> getSerializedObject() {
        Class<?> c = getClass();
        List<String> object = new ArrayList<String>(0);
        while (c != null && !c.equals(Response.class)) {
            object.addAll(0, serializeObject(c, this));
            c = c.getSuperclass();
        }
        c = null;
        return object;
    }
    public final List<String> getClassSignature() {
        Class<?> c = getClass();
        List<String> signature = new ArrayList<String>(0);
        while (c != null && !c.equals(Response.class)) {
            signature.addAll(0, describeClass(c));
            c = c.getSuperclass();
        }
        c = null;
        return signature;
    }
}

这些课程目前由'dev-test'程序驱动:

// Program.java
import com.jdgj.thinking.Response;
import com.jdgj.thinking.SpecificResponse;

public class Program {
    private static void printClassSignature(Response response) {
        for (String line : response.getClassSignature()) {
            System.out.println(line);
        }
    }
    private static void printSerializedObject(Response response) {
        for (String line : response.getSerializedObject()) {
            System.out.println(line);
        }
    }
    public static void main(String[] args) {
        String CN_SPECRSP = "com.jdgj.thinking.SpecificResponse";
        Class<?> response = null;
        try {
            response = Response.fromClassSignature(new SpecificResponse().getClassSignature());
        } catch (IllegalArgumentException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IllegalStateException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (ClassNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } finally {
            if (response != null) {
                System.out.println("Expected: " + CN_SPECRSP + "; Actually: " + response.getCanonicalName());
                Response rsp = null;
                try {
                    rsp = (Response)response.newInstance();
                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    if (rsp != null) {
                        //printClassSignature(rsp);
                        printSerializedObject(rsp);
                        rsp = null;
                    }
                }
                response = null;
            }
        }
    }
}

这是输出:

Expected: com.jdgj.thinking.SpecificResponse; Actually: com.jdgj.thinking.SpecificResponse
hell=null
trike=0
tail=0
thing2=0
value=null
class:com.jdgj.thinking.CommonResponse
field:thing2|int`0
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String`
field:trike|int`0
field:tail|short`0

为什么值报告为空

在没有和在CommonResponse中定义构造函数来初始化Value实例的情况下,它仍然显示为null。如果我取消注释Program.getClassSignature方法,代码将深入研究Value对象以获取five字段:

Expected: com.jdgj.thinking.SpecificResponse; Actually: com.jdgj.thinking.SpecificResponse
class:com.jdgj.thinking.CommonResponse
field:thing2|int
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.Value
field:five|int
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String
field:trike|int
field:tail|short
hell=null
trike=0
tail=0
thing2=0
value=null
class:com.jdgj.thinking.CommonResponse
field:thing2|int`0
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String`
field:trike|int`0
field:tail|short`0

我觉得好像我已经筋疲力尽了我的谷歌,我觉得我错过了一些只是......显而易见的事情,但我想不出原因,或者是对Google提出正确的查询。每个人都在不断提供获取原始字段的方法,但这不是我所追求的。因此,我接受了SO的指导。

1 个答案:

答案 0 :(得分:0)

正如霍尔格所说,你永远不会初始化那个领域。你有一个initialize()方法来做它,但永远不会调用它。 当然,如果你调用getClassSignature(),你会得到关于你的领域的信息,实际上它就在那里;你的类中有一个名为 com <。> com.jdgj.thinking.Value value 字段,但它从未被实例化,所以字段值为null。