使用来自 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
相反。
我有一个 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
相反。