Har*_*ish 117 java methods static final
我一直在玩静态方法的修饰符,并遇到了一个奇怪的行为.
我们知道,静态方法不能被覆盖,因为它们与类而不是实例相关联.
所以,如果我有下面的代码片段,它编译得很好
//Snippet 1 - Compiles fine
public class A {
static void ts() {
}
}
class B extends A {
static void ts() {
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我在A类中将final修饰符包含到静态方法中,则编译失败 ,B中的ts()不能覆盖A中的ts(); 重写方法是静态最终的.
当静态方法根本无法被覆盖时,为什么会发生这种情况?
Naw*_*Man 157
静态方法不能被覆盖,但可以隐藏它们.ts()
B 的方法不是覆盖(不受多态性)的ts()
A,但它会隐藏它.如果调用ts()
在B(NOT A.ts()
或B.ts()
...只是ts()
),B的一个将被调用,而不是A.因为这不会受到多态性,该呼叫ts()
在一个永远不会被重定向到一个在B.
该关键字final
将禁止隐藏该方法.因此它们无法隐藏,尝试这样做会导致编译器错误.
希望这可以帮助.
Vin*_*nie 12
静态方法无法覆盖
这不完全正确.示例代码实际上意味着B中的方法ts隐藏了A中的方法ts.所以它不完全覆盖.在Javaranch上有一个很好的解释.
考虑到以下因素,您可能会发现自己可以考虑制作静态方法.
有以下课程:
class A {
static void ts() {
System.out.print("A");
}
}
class B extends A {
static void ts() {
System.out.print("B");
}
}
Run Code Online (Sandbox Code Playgroud)
现在调用这些方法的"正确"方法是
A.ts();
B.ts();
Run Code Online (Sandbox Code Playgroud)
这会产生AB
但你也可以在实例上调用方法:
A a = new A();
a.ts();
B b = new B();
b.ts();
Run Code Online (Sandbox Code Playgroud)
这也会导致AB
.
现在考虑以下内容:
A a = new B();
a.ts();
Run Code Online (Sandbox Code Playgroud)
那将打印A
.这可能会让你感到惊讶,因为你实际上有一个类的对象B
.但是因为你是从类型的引用中调用它A
,它会调用A.ts()
.您可以B
使用以下代码进行打印:
A a = new B();
((B)a).ts();
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,您拥有的对象实际上来自类B
.但是,根据指向对象的指针,您将从A
或从中调用方法B
.
现在假设您是类的开发人员,A
并且您希望允许子类.但是你真的想要方法ts()
,无论什么时候被调用,甚至是从子类,这是你希望它做的事情,而不是被子类版本隐藏.然后你可以制作它final
并防止它隐藏在子类中.并且您可以确保以下代码将从您的类中调用该方法A
:
B b = new B();
b.ts();
Run Code Online (Sandbox Code Playgroud)
好吧,承认这是以某种方式构建的,但它可能对某些情况有意义.
您不应该在实例上调用静态方法,而是直接在类上调用 - 那么您就不会遇到这个问题.例如,IntelliJ IDEA会向您显示警告,如果您在实例上调用静态方法,并且如果您将静态方法调用为final.