如何使用反射获取对象字段的对象引用? [英] How to get the object reference of a field of an object using reflection?

查看:41
本文介绍了如何使用反射获取对象字段的对象引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:每次我输入这个问题时,我想我看到了一些东西,但它永远不会成功,所以第三次或第四次.

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

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

The code is as such (warning: large and not elegant), ordered from the specific class (SpecificResponse), as extended from a common class (CommonResponse), which is a concrete implementation of the abstract class (Response), driven by a test program (Program).

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

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

SpecifcResponse 扩展了 CommonResponse:

SpecifcResponse extends 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 对象:

For testing purposes, I just made a simple Value object:

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

public class Value {
    public int five;
}

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

And, that which does a lot of work, and also the foundation for CommonResponse, the Response class:

// 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;
    }
}

这些类目前由开发测试"程序驱动:

These classes are driven by a 'dev-test' program for now:

// 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 字段:

In both not having and having a constructor defined in CommonResponse to initialize the Value instance, it's still shown as null. If I uncomment the Program.getClassSignature method, the code delves into the Value object to get the five field:

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-fu,而且我觉得我遗漏了一些东西……显而易见,但我想不出原因,也想不出向 Google 提问的正确问题.每个人都不断提供获取原始字段的方法,但这不是我想要的.因此,我服从 SO 的指导.

I feel as if I've exhausted my Google-fu, and I feel like I'm missing something just.. blatantly obvious, but I cannot think of the reason, or the right query to ask Google. Everyone keeps providing ways to get primitive fields, but that is not what I am seeking. I therefore submit to the guidance of SO.

推荐答案

正如 Holger 所说,您从不初始化该字段.您有一个 initialize() 方法可以做到这一点,但永远不要调用它.当然,如果你调用 getClassSignature() 你会得到关于你的领域的信息,实际上它就在那里;你的类中有一个名为 value 的字段,类型为 com.jdgj.thinking.Value,但它从未被实例化,因此该字段值为空.

As Holger said you never initialize that field. You have a initialize() method to do it, but never invoke it. Of course if you call getClassSignature() you get info about your field, actually it's there; you got a field named value of type com.jdgj.thinking.Value in your class, but it never has been instantiated, so that field value is null.

这篇关于如何使用反射获取对象字段的对象引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆