使用来自 parent class 的反射更新字段

Updating field using reflection from parent class

我有一个 Parent class,它有一个使用反射来检索和更新字段的方法。此方法将由 child class

调用
package com.torchai.service.common.response;

import java.lang.reflect.Field;

public class TestReflection {
    private String foo;

    public void update() throws IllegalAccessException {
        final Field[] fields = getClass().getDeclaredFields();
        for (final Field f : fields) {
            //   f.setAccessible(true);
            //   final Object value = response.get(f.getName());
            Object value = "new value";
            f.set(this, value);

        }
    }

    public static void main(final String[] args) throws IllegalAccessException {
        final TestReflection t = new TestReflection() {
            private String abc;
        };

        t.update();
    }
}

当child class(在本例中为匿名class)调用继承自parent的方法时,this 是 child class。因此,我认为检索和设置私有字段不会有问题。原来 getDeclaredFields() 可以检索 private 字段,但是 Field.set() 不能更新它们,除非我 setAccessible 为真。这是正确的行为吗?为什么 child class 不能设置自己的字段?如果我可以看到该字段(即,我可以检索私有字段),我不应该能够更新它吗?

我得到的例外是

java.lang.IllegalAccessException: Class com.torchai.service.common.response.TestReflection can not access a member of class com.torchai.service.common.response.TestReflection with modifiers "private"

请注意,它暗示它正在尝试访问 child class parent class。为什么 parent class 被认为是来电者?

如果我改了main方法就不用了childclass

TestReflection t = new TestReflection();
t.update()

然后它按预期工作。 class 正在更新自己的字段,因此 setAccessbile 不是必需的

试图访问该字段的代码在 class TestReflection 中,这才是最重要的。没有迹象表明 subclass 愿意授予其 superclass 对其字段的访问权限,因为 private 意味着没有任何其他 class 的访问权限。 subclass 只是调用它的 superclass 的方法 update() 而不知道该方法在内部会做什么,所以它不是 subclass 试图访问 subclass的字段在这里。

更准确地说,在您的具体示例中,subclass 是 superclass 的嵌套 class,因此访问彼此的 private 成员是允许,但你遇到了反射的一个旧缺陷,只要嵌套 classes 存在就存在。当您使用目标 JDK 11 或更高版本编译示例时,此特定示例将起作用。

但对于顶级 classes,private 意味着没有其他 class 可以访问它(无需先启用访问覆盖),无论它是否是子[=声明 class 的 28=] 或 superclass。这似乎是您的实际问题。

请注意,使用像 getClass().getDeclaredFields() 这样的结构是很不寻常的。更多的是遍历发现的字段并设置所有字段。通常,您想知道您正在访问什么 class 和字段。在您的示例中,您尝试设置子 class 的字段 abc,但是当您将示例更改为 new TestReflection().update() 时,您设置的字段 foo TestReflection 相反。