Dav*_*les 30 java static overriding
根据这个答案和答案,Java静态方法不是虚拟的,不能被覆盖.因此,直观地说,这应该有效(即使在99%的情况下,这是危险的编程):
class Foo
{
public static String frob() {
return "Foo";
}
}
class Bar extends Foo
{
public static Number frob() {
return 123;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在实践中,这会让你:
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() {
^
Run Code Online (Sandbox Code Playgroud)
天真地,似乎Foo.frob()并且Bar.frob()应该与彼此无关; 然而Java坚持认为他们这样做.为什么?
(Nb:我不想听到为什么以这种方式编码是个坏主意,我想听听Java和/或JVM设计中的内容,这使得这个限制成为必要.)
更新以添加:对于那些认为编译器会因为在实例上调用静态方法而感到困惑的人,如果你允许这样做:它不会.它已经在方法签名的情况下算出这个是兼容的:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
得到你:
Foo
Foo
Bar
Run Code Online (Sandbox Code Playgroud)
问题是,为什么它不能那么容易(在不兼容签名的情况下)得到你的具体原因是什么:
Foo
Foo
123
Run Code Online (Sandbox Code Playgroud)
考虑以下:
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 Code Online (Sandbox Code Playgroud)
运行!它编译并打印出来
the thing
the thing
other thing
Run Code Online (Sandbox Code Playgroud)
静态方法是一种继承 - 在某种意义上B.doThing被转换为对A.doThing- 的调用- 并且可以被覆盖.
这似乎主要是对JLS的判断.但是,JLS似乎解决这个问题的最具体方法是8.2节,它并没有说静态方法不是继承的.