类无法使用来自不同包的反射访问其自己的受保护成员变量

时间:2018-02-11 13:24:49

标签: java reflection

我有三个类:一个基类A和两个类BC,它们都扩展AAB位于同一个包中,C位于不同的包中。

BC都有受保护的成员变量。 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);
        }
    }
}

非常感谢!

3 个答案:

答案 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不是BC的子类,因此子类的成员变量的可见性在此处不起作用。

但是,由于BA位于同一个包中,并且成员b被标记为protected,因此也是包可见,因此可以从A访问。

对于C,情况并非如此,因为A既不是C的子类,也不是CA在同一个包中