简体   繁体   中英

Class can't access its own protected member variable using reflection from different package

I have three classes: one base class A and two classes B and C that both extend A . A and B are in the same package and C is in a different package.

Both, B and C have a protected member variable. A has a method (lets call it reflect ) that uses reflection and a string input to accesses a field with this name of a subclass via the this pointer.

Calling reflect from a B object is fine, but calling it from a C object results in an IllegalAccessException. I can not understand this exception, because this means that C has no access rights to access its own member variable. Why doesn't java allow this reflection?

Here is a MWE to clarify what I mean:

In 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);
    }
}

In parent/B.java :

package Parent;
public class B extends A{
    protected Integer b;
    public B(Integer b){
        this.b = b;
    }
}

In 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;
    }
}

and a small main:

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);
        }
    }
}

Thank you very much!

Reflection allows you to bypass the access protection mechanism but you must explicitly instruct it to do so:

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);
    }
}

In particular, you may be having the issue with C because you're actually accessing C 's protected variable from A since that's where you're performing the reflective call. You'd get the same access violation if you tried accessing C 's field directly from A.reflect() .

The exception is quite clear:

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

The method is running under the namespace (=package) of class A.

The protected access modifier implies package-visibility.

Notice that A is not a subclass of B or C , therefore the visibility of member variables for subclasses plays no role here.

However, since B is in the same package as A , and the member b is marked as protected , it is also package-visible, and therefore can be accessed from A .

For C , this is not the case, because A is neither a subclass of C , nor is C in the same package as A .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM