当存储为超类时返回子类

时间:2020-07-24 14:03:01

标签: java class reflection

所以我已经尝试修复了几个小时,但无济于事。

基本上,我有A类和扩展B的{​​{1}}类。 A有一个字符串字段“ name”,而另一个字段“ id”,类A在实例化时更改了B。然后将name存储为B,并且将A类标识为A类的唯一内容是“ id”字段。

我需要一种从A类获取B类具有更改的“名称”的方法。

这是一个代码示例:

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会返回当前A对象的字段,这是我们已经拥有的。我需要实例化field.get(this)时更改的字段,但是当实例化B时,它会调用B几次,这会导致永久循环,我需要一种方法来从中获取字段getField而不实例化B

我尝试将B强制转换为A,但这会导致ClassCastException。

很抱歉,这很令人困惑,我无法发送整个类,因为它实际上是1k +行,但是基本上ID字段是A中存储的唯一数据,它仍然保留在B中,我需要一种方法来从B中获取字段B没有实例化

编辑:我认为我的示例令人困惑,这是pkm的答案仍然存在问题的一个示例。

B

2 个答案:

答案 0 :(得分:0)

这是更正的代码:

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 = "A_ID"; // is B_ID when changed

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


class B extends A {
  static {
    REGISTRY.put("B_ID", B.class);
  }

  public B() {
    name = "test1";
    id = "B_ID";
  }

}


public class Test {
  public static void main(String[] args) throws NoSuchFieldException, SecurityException,
      IllegalArgumentException, IllegalAccessException {
    A a = new B();
    System.out.println(a.name);                //--> output: test1
    System.out.println(a.getField("id"));      //--> output: B_ID
  }
}

根据您的陈述:I need a way to get the changed "name" that the B class has, from the A class.,它已正确实现,B_ID。

答案 1 :(得分:0)

通过将注册表从Class<? extends A>更改为A,然后注册B的新实例来解决此问题。我认为这可能会导致问题发展,我一直避免这样做,但目前仍然有效。