【问题标题】:Strange case of static method override in javajava中静态方法覆盖的奇怪案例
【发布时间】:2012-05-05 01:13:13
【问题描述】:

到处都写着不能覆盖静态方法,但是当我尝试将访问说明符从 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();            
    }
}

上面写着

不能降低继承方法的可见性

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

【问题讨论】:

  • “它遵循最重要的规则”:false。它打破了“不能降低继承方法的可见性”条款。你的问题到底是什么?
  • 在我看来,真正的问题是:禁止子类减少对“继承”静态方法的访问有什么好处?我能看到的唯一好处是 JLS 中的文本重用。

标签: java overriding


【解决方案1】:

它遵循一些相同的规则作为覆盖,但这并不意味着它覆盖的。在这种情况下,它是section 8.4.8.3 of the JLS,“覆盖和隐藏的要求”中的规则:

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

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

值得回顾第 8.4.8 节的其余部分,其中定义为发生在实例方法上的东西。

【讨论】:

  • 嗯,这让我很惊讶。不允许隐藏方法的可见性低于它隐藏的方法有什么意义?这对于可以多态调用的方法是有意义的,因为任何可以调用超类方法的东西也必须被允许调用子类方法。但对于隐藏而不是覆盖的静态方法,情况并非如此。
  • @Wyzard:我同意禁止降低可见性有点奇怪。但是,它可能试图避免您显式调用Subclass.foo() 的情况,这是一个通常解析为Superclass.foo() 的私有方法。无论哪种方式,它的行为都完全符合 JLS,而且它仍然不是压倒一切的。老实说,我建议不要在子类中声明与超类静态方法同名的静态方法。这只会导致混乱。
  • 为什么要避免这种情况?当意图调用 Superclass.foo() 时,程序员为什么要编写 Subclass.foo()?
  • @AlanSnyder:因为他们可能不知道更好。例如,我经常看到人们在 .NET 中写 UnicodeEncoding.UTF8,这令人困惑和奇怪。 (UTF8Encoding.UTF8 已经够糟糕了,但是使用 不同的 编码子类来访问Encoding.UTF8 是很奇怪的。但它确实发生了。)
  • 在这种情况下,IDE 可以帮助发出警告。
【解决方案2】:

您自己在问题中发布了答案,覆盖意味着在子类中为相同的方法使用不同的代码。由于无法覆盖静态方法,因此您无法通过修改访问说明符来使用可见性。

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 1970-01-01
    • 2011-01-04
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多