覆盖和弱化访问修饰符

Overriding and weaking access modifiers

根据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.

这似乎与以下代码不矛盾:

public class Main {

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

    public static void main(String[] args) {

    }
}

DEMO

但它没有编译,即使方法 f() 的覆盖版本具有 protected 访问修饰符,如我提供的规则的第二点所述。怎么了?

您不能使用更严格的访问修饰符覆盖方法。方法 f() 是使用访问修饰符 public 声明的,但您正试图使用​​更 限制性 protected 修饰符覆盖它。变化

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

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

在 JLS 的下方,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.

请注意,您在问题中引用的部分本质上是“基 class 中方法的访问修饰符不能是私有的”,并且与覆盖方法的访问修饰符完全无关.