[Java] Protected methods cannot always be called from within a subclass

Overview

One of Java's access modifiers is protected. Have you ever heard of protected as "accessible only within the same package and from subclasses"? I will tell you that this kind of understanding may lead to some misunderstandings.

I don't think there's anything particularly confusing about access from within the same package, so I'll only mention access from subclasses.

Target audience

Java beginner

environment

I checked the operation with Java11, but I think that the contents are not particularly different even with the old version.

Examples that don't work

With the understanding that it is "accessible from subclasses", the sample code below seems to work, but it actually results in a compile error. (Please forgive me for the naming sense ...)

package test.sp;

public class Super {
    protected void method() {
        System.out.println("Super#method() called.");
    }
}
package test.sub;
import test.sp.Super;

public class Sub extends Super {
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.run();
    }

    private void run() {
        Super sp = new Super();
        sp.method();  //error: method()Is protected by Super
    }
}

There is a Super class that has a method () method qualified with protected, and a Sub class that inherits that Super class. The Super class and Sub class are in separate packages, but since the Sub class inherits from the Super class (the Sub class is a subclass of the Super class), it is possible to call the method () method from the Sub class. There seems to be. However, the above code will result in a compilation error.

Examples that work

package test.sp;

public class Super {
    protected void method() {
        System.out.println("Super#method() called.");
    }
}
package test.sub;
import test.sp.Super;

public class Sub extends Super {
    public static void main(String[] args) {
        Sub sub = new Sub();
        sub.run();
    }

    private void run() {
        // (1)
        Sub sub = new Sub();
        sub.method();

        // (2)
        this.method();

        // (3)
        method();

        // (4)
        super.method();
    }
}

This time it works, but the Super class and the relationship between the Super class and the Sub class haven't changed, only the way they are called from the Sub class. There are (1) to (4), but all of them compile and worked without any error at runtime.

// (1)
Sub sub = new Sub();
sub.method();

(1) explicitly creates an instance of the Sub class and calls method () for that instance. I got a compile error on the instance of Super class, but it seems that there is no problem if it is an instance of Sub class.

// (2)
this.method();

// (3)
method();

(2) is a call with this. This also works. (3) is substantially the same as (2) except that the description of this is omitted. Since this points to its own instance, all of (1) to (3) are the same in the sense that it calls method () of the instance of the Sub class.

// (4)
super.method();

(4) is slightly different from (1) to (3). (4) calls super's method (), which also works. super refers to an instance of a superclass (associated with itself). When I explicitly created an instance of the Super class and called method () for that instance, a compile error occurred, but if it is super, there is no problem. I thought that they would behave the same because they are all instances of Super class, but the result was a little surprising.

Summary

For methods qualified with protected, the visibility from subclasses defined in another package is as follows.

--In a subclass, you can call it from an instance of the subclass itself that was explicitly created by new. --Can be called from this in the subclass. The same applies when calling without the description of this --Can be called from super in the subclass --Cannot be called from an instance of a superclass explicitly created by new in a subclass --Understanding protected visibility as "accessible only within the same package and from subclasses" can lead to the misunderstanding that you can call for the above non-callable patterns.

Serpentine

You may see methods that appear to be protected and qualified with the intention that they can only be called from within the same package, but in this case you should use package private (no qualifier) instead of protected. I don't use protected personally. (Maybe you don't understand how to use it ...)

Recommended Posts

[Java] Protected methods cannot always be called from within a subclass
Kotlin's reified function cannot be called from java.
jsf.ajax.request: Method must be called within a form
Java Stream cannot be reused.
Run a batch file from Java
Access Teradata from a Java application
Java to be involved from today
Java cannot be installed on Ubuntu 13.04
Java code that cannot be used from Kotlin (for in-house study sessions)