覆盖和削弱访问修饰符

St.*_*rio 1 java overriding jls

根据JLS 8.4.8.1

在类C中声明的实例方法m1将覆盖在类A中声明的另一个实例方法m2,如果以下所有条件都为真:

  • C是A的子类.

  • m1的签名是m2签名的子签名(§8.4.2).

  • 或者:

    • m2在与C相同的包中是公共的,受保护的或声明的,具有默认访问权限

    • m1覆盖方法m3(m3与m1不同,m3与m2不同),使得m3覆盖m2.

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

public class Main {

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

    public static void main(String[] args) {

    }
}
Run Code Online (Sandbox Code Playgroud)

DEMO

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

Chr*_*yes 6

在JLS中,8.4.8.3中提供了较低的理由:

覆盖或隐藏方法的访问修饰符(第6.6节)必须至少提供与重写或隐藏方法一样多的访问权限,如下所示:

  • 如果重写或隐藏方法是公共的,则覆盖或隐藏方法必须是公共的; 否则,发生编译时错误.

  • 如果被覆盖或隐藏的方法受到保护,则覆盖或隐藏方法必须受到保护或公开; 否则,发生编译时错误.

  • 如果重写或隐藏方法具有默认(包)访问权限,则覆盖或隐藏方法不得为私有方法; 否则,发生编译时错误.

请注意,您在问题中引用的部分基本上指出"基类中方法的访问修饰符不能是私有的",并且根本不涉及覆盖方法的访问修饰符.