Search code examples
javavisibilityprotectedaccess-modifiers

Understanding Java's protected modifier


I have a class called A in package1 and another class called C in package2. Class C extends class A.

A has an instance variable which is declared like this:

protected int protectedInt = 1;

Here is the code for class A

package package1;

public class A {
    
    public int publicInt = 1;
    private int privateInt = 1;
    int defaultInt = 1;
    protected int protectedInt = 1;

}

And here is the code for class C:

package package2;
import package1.A;

public class C extends A{

    public void go(){
        //remember the import statement
        A a = new A();
        System.out.println(a.publicInt);
        System.out.println(a.protectedInt);
        
    }
}

Eclipse underlines the last line in C.go() and says "A.protectedInt" is not visible. It seems that this conflicts with the definition of the "protected" keyword, given the Oracle documentation says:

The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

What's going on here?


Solution

  • What's going on here?

    You've misunderstood the meaning of protected. You can access the protected members declared in A from within C, but only for instances of C or subclasses of C. See section 6.6.2 of the JLS for details of protected access. In particular:

    Let C be the class in which a protected member is declared. Access is permitted only within the body of a subclass S of C.

    In addition, if Id denotes an instance field or instance method, then:

    • [...]

    • If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

    (Emphasis mine.)

    So this code would be fine:

    C c = new C();
    System.out.println(c.publicInt);
    System.out.println(c.protectedInt);