Skip to content
Advertisement

Why is package-protected method not visible in the same package?

Assume we have two packages p1 and p2 and classes p1.M1 extended by p2.M12 as follows:

package p1;

public class M1 {
    void method1() {
        System.out.println("Method 1 called");
    }
}


package p2;

import p1.M1;

public class M12 extends M1 {
    void method2() {
        System.out.println("Method 2 called");
    }
}

Let’s extend M12 with p2.B:

package p2;

public class B extends M12 {

    public void doSomething()  {
        method1();
        method2();
    }
} 

This gives a compilation error as method1, being package-protected within p1 is not visible in p2. method2 is visible without problems.

Now let’s extend p2.M12 with p1.A:

package p1;

import p2.M12;

public class A extends M12 {

    public void doSomething() {
        method1();
        method2();
    }
}

Here I’m getting a compilation error for both method2() (which is understandable) and method1(): The method method1 from the type M1 is not visible

My question is: why is the method1 which is package-protected in the package p1 is not visible in the class A from the same package p1?

Advertisement

Answer

First, what is a member of a class? The Java Language Specification states

A class body may contain declarations of members of the class, that is, fields (§8.3), methods (§8.4), classes (§8.5), and interfaces (§8.5).

And what are they composed of? The JLS states

The members of a class type are all of the following:

  • Members inherited from its direct superclass (§8.1.4), except in class Object, which has no direct superclass
  • Members inherited from any direct superinterfaces (§8.1.5)
  • Members declared in the body of the class (§8.1.6)

It also mentions

Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in which the class is declared.

All of this is reworded in the chapter on Inheritance

A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:

  • m is a member of the direct superclass of C.
  • m is public, protected, or declared with package access in the same package as C`.
  • No method declared in C has a signature that is a subsignature (§8.4.2) of the signature of m.

The members of class M1 are method1 (and all the methods of Object). M12, being in a different package than its direct superclass, M1, does not inherit method1. The members of M12 are therefore only method2.

The direct superclass of B is M12 and is in the same package. It therefore inherits its member, method2. B knows nothing about method1. If you had compiled your code with javac, you would have received a cannot find symbol compilation error instead. (It seems Eclipse is trying to guess what you were trying to do.)

Similarly, the direct superclass of A is M12, but is in a different package. It does not inherit method2 for that reason. A doesn’t know anything about method1 or method2 because it didn’t inherit them. Both of those symbols cannot be found.

Advertisement