【发布时间】:2020-11-14 09:59:13
【问题描述】:
所以我已经尝试修复这个问题几个小时了,但无济于事。
基本上,我有 A 类和 B 类扩展 A。 A 有一个字符串字段“name”,另一个字段“id”,类B 在实例化时更改name。然后B 被存储为A,唯一将A 类标识为B 类的是“id”字段。
我需要一种方法来从 A 类中获取 B 类所具有的更改后的“名称”。
这是一个代码示例:
class A {
public String name = "test";
public String id = "A_ID";
public A(String id) {
if (id.equals("B_ID") {
// how would I get the name field of the B class, without instantiating B
}
}
}
class B extends A {
{
name = "test1";
id = "B_ID";
}
}
这是我尝试过的:
class A {
public static Map<String, Class<? extends A>> REGISTRY = new HashMap<>();
public String name = "test";
public String id = "A_ID"; // is B_ID when changed
public Object getField(String key) {
Field field = REGISTRY.get(this.id).getSuperclass().getDeclaredField(key);
return field.get(this); // <- the issue
}
}
class B extends A {
static {
REGISTRY.put("B_ID", B.class);
}
public B() {
name = "test1";
id = "B_ID";
}
}
这是我的解决方案的问题,将this 传递给field.get(this) 返回当前A 对象的字段,这是我们已经拥有的。我需要B 在实例化时更改的字段,但是当B 被实例化时,它会调用getField 几次,这会导致永久循环,我需要一种方法来从B 获取字段而不实例化@ 987654340@.
我尝试将 A 转换为 B 但这会导致 ClassCastException。
抱歉,这令人困惑,我无法发送整个类,因为它实际上是 1k+ 行,但基本上 ID 字段是与 A 一起存储的唯一数据,但仍来自 B,我需要一种方法来获取来自 B 的字段B 没有实例化它
编辑:我认为我的示例令人困惑,这是 pkm 的答案仍然存在问题的示例。
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
class A {
public static Map<String, Class<? extends A>> REGISTRY = new HashMap<>();
public String name = "test";
public String id; // is B_ID when changed
public A(String id) {
this.id = id;
this.getField("name") // should output test1
}
public Object getField(String key) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
Field field = REGISTRY.get(this.id).getSuperclass().getDeclaredField(key);
return field.get(this); // <- the issue, still returns "test"
}
}
class B extends A {
static {
REGISTRY.put("B_ID", B.class);
}
public B() {
super("B_ID");
name = "test1";
}
}
public class main {
public static void main(String[] args) throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
new B(); // To update the registry
A a = new A("B_ID");
System.out.println(a.id); //--> output: B_ID
System.out.println(a.getField("name")); //--> output: test, should be test1
}
}
【问题讨论】:
-
检查`if (this instanceof B)`不够吗?
-
就像我说的那样,它都存储为 A。没有什么是 B 的实例,所以向下转换为 B 会导致 ClassCastException
-
“没有什么是 B 的实例”——当然,您通过
new B()创建的实例除外。由于您发布的代码更改了该B实例的字段,但您没有保留对该对象的引用,因此无法使用该代码检索该值。不清楚你为什么在这里使用反射,也许只是为了隐藏试图获得你已经放弃的值的基本逻辑错误。但是由于所有实例都在构造函数中获取该值,因此您可以使用REGISTRY.get("B_ID").getConstructor().newInstance().name获取该值,但仍然过度设计。 -
您不知何故忘记提及您的问题与 JSON 序列化有关。除此之外,还有什么问题?该字段在
A中声明,因此在反序列化A实例后,它仍将包含在序列化之前存储在原始B实例中的值。当然,由于您的示例代码不包含任何序列化/反序列化,因此示例代码中不会发生这种情况。在您的示例中,没有实例,只有 类 和构造函数提供的常量的注册表,根本不需要持久性。
标签: java class reflection