英文:
Calling java.lang.reflect.Field::getValue(this) from abstract superclass defined method returns IllegalAccessException
问题
I'm trying to print the whole hierarchy of a class using reflection.
To do this I defined an abstract superclass A that defines the toString(int offset)
method:
abstract class A {
public String toString(int offset) {
StringBuilder builder = new StringBuilder();
try {
for (Field field : this.getClass().getDeclaredFields()) {
builder.append(String.join(" ", Collections.nCopies(offset, "\t")));
builder.append(field.getName()).append(": ");
field.setAccessible(true); // workaround
if (field.getType().isPrimitive()) {
// (int, float, ...)
builder.append(field.get(this));
} else if (field.getType().getName().contains("java.lang")) {
// (Integer, String, ...)
builder.append(field.get(this).toString());
} else {
// Other classes
builder.append("\n").append(A.class.cast(field.get(this)).toString(offset + 1));
}
builder.append("\n");
field.setAccessible(false); // workaround
}
} catch (Exception e) {
System.out.print(e);
}
return builder.toString();
}
}
then I have some classes that extend the A class:
public class X extends A {
private String field1;
private Y field2;
}
public class Y extends A {
private String field3;
private String field4;
}
which instances contain some values.
The expected output of the call x.toString(0)
should be:
field1: value1
field2:
field3: value3
field4: value4
Without the use of field.setAccessible(true)
when I call x.toString(0)
I get
IllegalAccessException: Class A can not access a member of class X with modifiers "private"
but I cannot understand why.
When I check the reference while debugging this
refers to X.class, so why the field.getValue(this)
doesn't work?
Shouldn't this
refer to the instance of the class calling the method? Am I missing something?
英文:
I'm trying to print the whole hierarchy of a class using reflection.
To do this I defined an abstract superclass A that defines the toString(int offset)
method:
abstract class A {
public String toString(int offset) {
StringBuilder builder = new StringBuilder();
try {
for (Field field : this.getClass().getDeclaredFields()) {
builder.append(String.join("", Collections.nCopies(offset, "\t")));
builder.append(field.getName()).append(": ");
field.setAccessible(true); // workaround
if (field.getType().isPrimitive()) {
// (int, float, ...)
builder.append(field.get(this));
} else if (field.getType().getName().contains("java.lang")) {
// (Integer, String, ...)
builder.append(field.get(this).toString());
} else {
// Other classes
builder.append("\n").append(A.class.cast(field.get(this)).toString(offset + 1));
}
builder.append("\n");
field.setAccessible(false); // workaround
}
} catch (Exception e) {
System.out.print(e);
}
return builder.toString();
}
}
then I have some classes that extend the A class:
public class X extends A {
private String field1;
private Y field2;
}
public class Y extends A {
private String field3;
private String field4;
}
which instances contains some values.
The expected output of the call x.toString(0)
should be:
field1: value1
field2:
field3: value3
field4: value4
Without the use of field.setAccessible(true)
when I call x.toString(0)
I get
IllegalAccessException: Class A can not access a member of class X with modifiers "private"
but I cannot undestand why.
When I check the reference while debugging this
refers to X.class, so why the field.getValue(this)
doesn't work?
Shouldn't this
refer to the instance of the class calling the method? Am I missing something?
答案1
得分: 4
private
不表示它是私有的 实例;它表示它是私有的 类。继承并不能豁免这一点(只有 protected
有限制的例外)。在 A
中,下面的例子无法编译通过,因为 field2
是不可访问的:
X x = (X)this;
System.out.println(x.field2);
反射默认也遵循相同的限制。
英文:
private
doesn't mean it's private to the instance; it means it's private to the class. Inheritance doesn't offer any exemption from that (with the limited exception of protected
). The following example would fail to compile in A
because field2
is inaccessible:
X x = (X)this;
System.out.println(x.field2);
Reflection imposes the same restrictions by default.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论