Search code examples
javaoverridingjls

Overriding and weaking access modifiers


According to the JLS 8.4.8.1

An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:

  • C is a subclass of A.

  • The signature of m1 is a subsignature (§8.4.2) of the signature of m2.

  • Either:

    • m2 is public, protected, or declared with default access in the same package as C, or

    • m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.

This doesn't appear to contradict the following code:

public class Main {

    public void f() { }
    public static class A extends Main {
        protected void f() { }
    }

    public static void main(String[] args) {

    }
}

DEMO

But it's not compiling, even though the overridden version of the method f() has the protected access modifier, as said in the second point of the rule I provided. What's wrong?


Solution

  • The justification for this is provided lower in the JLS, in 8.4.8.3:

    The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:

    • If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.

    • If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.

    • If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.

    Note that the section you've quoted in your question essentially states "the method's access modifier in the base class must not be private", and doesn't relate to the overriding method's access modifier at all.