为什么Java为重写的静态方法强制执行返回类型兼容性? [英] Why does Java enforce return type compatibility for overridden static methods?

查看:97
本文介绍了为什么Java为重写的静态方法强制执行返回类型兼容性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据此答案这个答案,Java静态方法不是虚拟的,不能被覆盖。因此,直观地说,这应该有效(即使在99%的情况下它是危险的编程):

  class Foo 
{
public static String frob(){
returnFoo;
}
}

class Bar扩展Foo
{
public static Number frob(){
return 123;
}
}

然而,实际上这会让你:

  Bar中的Foo.java:10:fob()不能覆盖Foo中的frob();尝试使用不兼容的返回类型
found:java.lang.Number
required:java.lang.String
public static Number frob(){
^

天真地,好像是 Foo.frob() Bar.frob()应该与彼此无关;然而Java坚持认为他们这样做。为什么?



(Nb:我不想听到为什么以这种方式编码会是一个坏主意,我想听听Java中的内容和/或必须进行此限制的JVM设计。)






已更新以添加:对于那些谁认为编译器会因为在实例上调用静态方法而感到困惑,如果允许的话:它不会。它必须在方法签名 兼容的情况下解决这个问题:

  class Foo 
{
static String frob(){
returnFoo;
}
}

class Bar扩展Foo
{
static String frob(){
returnBar;
}
}

class Qux {
public static void main(String [] args){
Foo f = new Foo();
Foo b = new Bar();
Bar b2 = new Bar();

System.out.println(f.frob());
System.out.println(b.frob());
System.out.println(b2.frob());
}
}

获取:

  Foo 
Foo
Bar

问题是,为什么不能轻易地(在不兼容的签名案例中)得到你的具体原因是什么:

  Foo 
Foo
123


解决方案<考虑以下内容:

  public class Foo {
static class A {
public static void doThing(){
System.out.println(the thing);
}
}

静态类B扩展A {

}

静态类C扩展B {
public static void doThing(){
System.out.println(other thing);
}
}

public static void main(String [] args){
A.doThing();
B.doThing();
C.doThing();
}
}

运行它!它编译并打印出来

 东西
东西
其他东西

静态方法是一种继承 - 从 B.doThing 的意义上来说转换为对 A.doThing 的调用 - 并且可以被覆盖。



这似乎是主要是对JLS的判断。然而,JLS似乎解决这个问题的最具体方式是第8.2节,它并不是说静态方法不是继承的。


Per this answer and this answer, Java static methods aren't virtual and can't be overridden. Intuitively, therefore, this should work (even if in 99% of cases it's dangerous programming):

class Foo
{
    public static String frob() {
        return "Foo";
    }
}

class Bar extends Foo
{
    public static Number frob() {
        return 123;
    }
}

However, in practice this gets you:

Foo.java:10: frob() in Bar cannot override frob() in Foo; attempting to use incompatible return type
found   : java.lang.Number
required: java.lang.String
    public static Number frob() {
                         ^

Naively, it seems like Foo.frob() and Bar.frob() should have nothing to do with one another; yet Java insists that they do. Why?

(N.b.: I don't want to hear why it would be a bad idea to code this way, I want to hear what it is in Java and/or the JVM design that makes this restriction necessary.)


Updated to add: For those who think the compiler's going to get confused by calling static methods on instances, if you allow this: it won't. It already has to figure this out in the case where the method signatures are compatible:

class Foo
{
    static String frob() {
        return "Foo";
    }
}

class Bar extends Foo
{
    static String frob() {
        return "Bar";
    }
}

class Qux {
    public static void main(String[] args) {
        Foo f = new Foo();
        Foo b = new Bar();
        Bar b2 = new Bar();

        System.out.println(f.frob());
        System.out.println(b.frob());
        System.out.println(b2.frob());
    }
}

gets you:

Foo
Foo
Bar

The question is, what's the concrete reason why it couldn't as easily (in the incompatible-signatures case) get you:

Foo
Foo
123

解决方案

Consider the following:

public class Foo {
  static class A {
    public static void doThing() {
      System.out.println("the thing");
    }
  }

  static class B extends A {

  }

  static class C extends B {
    public static void doThing() {
      System.out.println("other thing");
    }
  }

  public static void main(String[] args) {
    A.doThing();
    B.doThing();
    C.doThing();
  }
}

Run it! It compiles and prints out

the thing
the thing
other thing

Static methods sort of inherit -- in the sense that B.doThing is translated into a call to A.doThing -- and can sort of be overridden.

This seems like it was mostly a judgement call for the JLS. The most specific way the JLS seems to address this, though, is section 8.2, which simply doesn't say that static methods aren't inherited.

这篇关于为什么Java为重写的静态方法强制执行返回类型兼容性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆