为什么Java为重写的静态方法强制执行返回类型兼容性? [英] Why does Java enforce return type compatibility for overridden static methods?
问题描述
根据此答案和这个答案,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屋!