Calling java.lang.reflect.Field::getValue(this) from abstract superclass defined method returns IllegalAccessException

huangapple go评论59阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年5月11日 00:12:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220603.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定