java中静态方法覆盖的奇怪情况

Jyo*_*rup 3 java overriding

它写在任何地方都不能覆盖静态方法,但是当我尝试减少访问说明符时,从public到protected,它会产生错误.例如

public class StaticOverrideFunda {

    public static void foo(){
        System.out.println("Parent Foo");
    }
}

public class B extends StaticOverrideFunda{


    protected static void foo(){
        System.out.println("Child Foo");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        B.foo();            
    }
}
Run Code Online (Sandbox Code Playgroud)

它说

无法降低继承方法的可见性

因此,它是遵循最重要的规则,为什么我们说foo没有在B类中被覆盖?为什么我们说它隐藏/阴影而不是覆盖?

Jon*_*eet 8

它遵循一些与覆盖相同的规则,但这并不意味着它压倒一切的.在这种情况下,它是JLS第8.4.8.3节中的规则,"覆盖和隐藏的要求":

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

它仍然没有覆盖,因为该方法不会被多态调用 - 你不能写一个有时会最终调用StaticOverrideFunda.foo有时最终调用的调用B.foo; 目标完全在编译时确定.

值得回顾8.4.8节的其余部分,它将覆盖定义为实例方法中出现的内容.

  • 嗯,这对我来说很意外.有什么不允许隐藏方法比它隐藏的方法具有更少的可见性?对于可以多态调用的方法是有意义的,因为必须允许任何可以调用超类方法的方法来调用子类.但是静态方法不是隐藏而是覆盖的情况. (2认同)
  • @Wyzard:我同意禁止降低能见度有点奇怪。然而,它可能试图避免显式调用“Subclass.foo()”的情况,这是一个私有方法,“通常”会解析为“Superclass.foo()”。不管怎样,它的行为完全符合 JLS,而且仍然没有压倒一切。老实说,我建议不要在子类中声明与超类静态方法同名的静态方法。这只会导致混乱。 (2认同)