【问题标题】:Java reflection field value in extends class [duplicate]扩展类中的Java反射字段值[重复]
【发布时间】:2012-09-19 15:18:16
【问题描述】:

可能重复:
Access to private inherited fields via reflection in Java

您好,我遇到了 java 反射的 init 值问题。

我有简单的课程

 public class A extends B {
     private String name;
 }

  public class B {
     private String superName;   
  }

我也有简单的功能:

   public void createRandom(Class<T> clazz , List<String> classFields){


    try {
        T object = clazz.newInstance();
        for(String s : classFields){
            clazz.getDeclaredField(s);
        }

    } catch(Exception e){

    }

   }

我的函数做其他事情,但我遇到了问题,因为我有错误:

java.lang.NoSuchFieldException: superName

如何使用反射设置所有类字段以及超类中的字段??

我有所有的类字段(也是继承的),我正在使用函数field.set(Object obj, Object value),但这样我不能设置继承的类字段:/

我没有遇到问题来获取我正在使用 Spring ReflectionUtils.doWithfield 的所有类字段。 我将所有字段名称存储在List&lt;String&gt; classField 中,所以我知道所有 clazz 字段也继承了。但我的问题是如何为所有 clazz 字段设置值。

【问题讨论】:

  • 你是如何调用createRandom()的? clazz 和列表的值是什么?

标签: java reflection


【解决方案1】:

如果我不得不猜测,我假设您正在 A 类上调用此方法,并期望能够查看 B 类中声明的底层字段,如下所示:

A.class.getDeclaredField("superName");

情况并非如此,并且会引发异常 (java.lang.NoSuchFieldException)。反射不检查超类来查找字段或方法。因此,由于类A 没有定义superName,因此使用这样的反射将找不到它。但是,您可以修改您的代码以使其检查所有超类,直到它达到null 作为超类,此时如果仍未找到它,则它肯定不存在。

这是一个例子:

public static Field findUnderlying(Class<?> clazz, String fieldName) {
    Class<?> current = clazz;
    do {
       try {
           return current.getDeclaredField(fieldName);
       } catch(Exception e) {}
    } while((current = current.getSuperclass()) != null);
    return null;
}

这是一个示例调用:findUnderlying(A.class, "superName");它会首先检查 A 类的字段。由于 A 没有它,所以 dowhile 会转到它的超类,即 B (不为空,所以继续)。 B 确实有它,因此它会返回该字段。如果 B 没有它,它会检查 Object,然后返回 null,因为 Object 没有超类。

【讨论】:

  • +1 为方法,但您永远不应该重新分配方法参数(在这种情况下为clazz)。
  • @aymeric 是的,谢谢,实际上是我以前编辑它的方式,但是改变了它,没有考虑它:)
  • 但我知道如何获取所有类字段(也继承)。但我的问题是如何设置所有字段值?我发现只有一种方法可以做到这一点:field.set(Object obj,Object value),但是这种方法不能允许设置继承的字段:/
  • @Lukasz Wozniczka 如果你打电话给someFieldOfSuperClass.set(subClassOfClassWithField, value),它仍然可以工作
【解决方案2】:

你可以使用:

clazz.getSuperclass().getDeclaredField(s);

代替(或加上一些try-catch):

clazz.getDeclaredField(s);

编辑:

要设置超类的值,请使用以下命令:

Field f = clazz.getSuperclass().getDeclaredField(s);
f.setAccessible(true); // Especially necessary if the field is not public
f.set(yourObject, theValue);

【讨论】:

  • 是的,我知道。但是如何将值设置为继承的类字段??
  • @ŁukaszWoźniczka 查看我的编辑...
【解决方案3】:

使用Class.getSuperclass() 获取超级类。然后使用超类,你可以得到它的字段。

【讨论】:

    【解决方案4】:

    即使 A 从 B 扩展,它也不适用于 A 的实例,这是因为子类中无法访问私有成员。尝试将 superName 的访问权限更改为受保护,如果它有效...

    【讨论】:

    • 我不认为改变类定义中的可见性是解决方案,OP 正在寻找如何访问私有字段的方法
    • 不改变可见性允许您使用私有修饰符将值保存到字段中。
    猜你喜欢
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多