我有三个类:一个基类A
和两个类B
和C
,它们都扩展A
。 A
和B
位于同一个包中,C
位于不同的包中。
B
和C
都有受保护的成员变量。 A
有一个方法(让我们称之为reflect
),它使用反射和字符串输入来通过this
指针访问具有此子类名称的字段。
从reflect
对象调用B
很好,但是从C
对象调用它会导致IllegalAccessException。我无法理解此异常,因为这意味着C
无权访问其自己的成员变量。为什么java不允许这种反思?
这是一个MWE来澄清我的意思:
在parent/A.java
:
package Parent;
public abstract class A {
public Object reflect(String parameter) throws NoSuchFieldException, IllegalAccessException{
Class cl = getClass();
return cl.getDeclaredField(parameter).get(this);
}
}
在parent/B.java
:
package Parent;
public class B extends A{
protected Integer b;
public B(Integer b){
this.b = b;
}
}
在parent/child/C.java
:
package Parent.Child;
import Parent.A;
public class C extends A{
protected Integer c;
public C(Integer c){
this.c = c;
}
}
和一个小主要:
import Parent.A;
import Parent.B;
import Parent.Child.C;
public class test {
public static void main(String args[]) {
B j1 = new B(10);
C j2 = new C(20);
try{
Integer b_copy = (Integer)j1.reflect("b");
System.out.println(b_copy); // prints "10"
Integer c_copy = (Integer)j2.reflect("c"); // throws java.lang.IllegalAccessException: Class Parent.A can not access a member of class Parent.Child.C with modifiers "protected"
System.out.println(c_copy);
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println(e);
}
}
}
非常感谢!
答案 0 :(得分:2)
Reflection允许您绕过访问保护机制,但您必须明确指示它执行此操作:
package Parent;
public abstract class A {
public Object reflect(String parameter) throws NoSuchFieldException, IllegalAccessException{
Class cl = getClass();
java.lang.reflect.Field f = cl.getDeclaredField(parameter);
f.setAccessible(true);
return f.get(this);
}
}
特别是,您可能遇到C
的问题,因为您实际上正在从C
访问A
的受保护变量,因为您正在执行反射调用。如果您尝试直接从C
访问A.reflect()
的字段,则会受到相同的访问冲突。
答案 1 :(得分:1)
异常非常清楚:
java.lang.IllegalAccessException: Class Parent.A can not access a member of class Child.C with modifiers "protected"
该方法在A类的名称空间(= package)下运行。
答案 2 :(得分:1)
protected
访问修饰符意味着包可见性。
请注意,A
不是B
或C
的子类,因此子类的成员变量的可见性在此处不起作用。
但是,由于B
与A
位于同一个包中,并且成员b
被标记为protected
,因此也是包可见,因此可以从A
访问。
对于C
,情况并非如此,因为A
既不是C
的子类,也不是C
与A
在同一个包中