【问题标题】:Class can't access its own protected member variable using reflection from different package类无法使用来自不同包的反射访问其自己的受保护成员变量
【发布时间】:2018-07-21 18:22:38
【问题描述】:

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

BC 都有一个受保护的成员变量。 A 有一个方法(我们称之为reflect),它使用反射和字符串输入通过this 指针访问具有此子类名称的字段。

B 对象调用reflect 很好,但是从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);
        }
    }
}

非常感谢!

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    protected 访问修饰符意味着包可见性。

    请注意A 不是BC 的子类,因此子类的成员变量的可见性在这里不起作用。

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

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

    【讨论】:

      【解决方案2】:

      反射允许您绕过访问保护机制,但您必须明确指示它这样做:

      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 的问题,因为您实际上是从A 访问C 的受保护变量,因为这是您执行反射调用的地方。如果您尝试直接从 A.reflect() 访问 C 的字段,您会遇到相同的访问冲突。

      【讨论】:

      • 谢谢!但为什么首先会出现问题?为什么C不允许访问自己的受保护字段?
      • 访问受保护字段的方法在A 中定义。如果您使用A 中完全相同的主体覆盖C 中的方法,它会起作用,因为您将访问C 中的受保护方法。如果您尝试在A.reflect() 中执行((C) this).c;,您会看到“C.c 字段不可见”。
      • 啊,我明白了。再次感谢您
      【解决方案3】:

      异常很明显:

      java.lang.IllegalAccessException: Class Parent.A can not access a member of class Child.C with modifiers "protected"
      

      该方法在类 A 的命名空间(=package)下运行。

      【讨论】:

      • 谢谢!我不清楚该方法是否被视为来自C 的方法。
      猜你喜欢
      • 2013-03-14
      • 1970-01-01
      • 2015-09-19
      • 2016-05-25
      • 2014-02-22
      • 2015-12-11
      • 2011-03-29
      • 2012-05-14
      • 2015-01-30
      相关资源
      最近更新 更多