如何使用反射获取对象字段的对象引用? [英] How to get the object reference of a field of an object using reflection?
问题描述
注意:每次我输入这个问题时,我想我看到了一些东西,但它永远不会成功,所以第三次或第四次.
概要:我正在尝试使用 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屋!