如果静态方法不能被覆盖,它在这里是如何工作的(For Java)?
If static methods can't be overridden, how its working here (For Java)?
我的理解是静态变量和静态方法属于class,而不是class objects。因此静态方法的 Override
在 Java 中不起作用,至于覆盖我们需要创建一个 class 的实例。但我今天正在尝试一些与我对 Java.
的知识相矛盾的事情
请遵循此代码:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Child ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上实现的输出为:
D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Child
从这个输出我可以了解到,虽然 Child
class 扩展了 Parent
class,但 doit
方法对于每个 class 因为它们是 static
。所以不允许覆盖它们。
现在请按照下面的代码,其中 @Override
添加到 child 的 doIt
方法中:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
@Override // Adding this annotation here
public static void doIt(){
System.out.println("In static method 'doit' of class Child ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上代码的输出给出如下编译错误:
D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:31: error: method does not override or implement a method from a supertype
@Override
^
1 error
这里明确指出注释 Override
不能应用于 static
方法,因为它们不会被覆盖。
现在请按照下面的代码,其中 Child
没有 doIt
方法:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{ /* no doIt method */ }
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
输出为:
D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Parent
为什么上面的代码可以编译运行?我期待 class Child 的方法 doit
的编译错误,我期待 "Method not found"。没看懂。
也请按照下面的代码。这里,Parent
中的 doIt
方法现在是 final
.
class Parent{
public static final void doIt(){ // now final
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上代码运行后输出如下:
D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent
public static void doIt(){
^
overridden method is static,final
1 error
D:\Rahul Shivsharan\MyPractise\JAVA>
我所期望的是上面的代码应该可以正常工作,因为 doit
方法在每个 class 中都是静态的,所以即使是 final
关键字也不应该产生任何编译错误因为方法是 static
。
请向我解释方法重写在 Java.
中的静态 classes 中是如何工作的
- 静态方法可以重写吗?如果是,那么注释
@Override
怎么会失败?
- 如果不能覆盖静态方法,那我的第三个代码块运行怎么没问题?
- 如果不能重写静态方法,那么
final
关键字有何不同?
你搞糊涂了overriding with hiding
首先,这里涉及不同的机制:Overriding and Shadowing (also called hiding)。
1)
静态方法不能被覆盖,因为它们附加到它们在其中定义的 class。但是,您可以 shadow/hide 一个静态方法,就像您对 Parent
/Child
class。这意味着,该方法在 Child
class 中被替换,但在 Parent
class.
中仍然可用
当您从那些 classes 的实例调用静态方法时(并且不使用 Class.staticMethod()
调用)。
Parent parent = new Parent();
Child child1 = new Child();
Parent child2 = new Child();
parent.StaticMethod();
child1.StaticMethod();
child2.StaticMethod();
输出是
Static method from Parent
Static method from Child
Static method from Parent
答案是方法的调度。你可以抓住 source code here
2)
调度在 Parent
class 上找到方法。没有动态调度,因为运行时类型用于查找方法句柄。它使用编译时类型。 提醒:从实例调用静态方法被认为是不好的做法,因为像上面这样的事情可能会发生并且很容易被忽视。
3)
使用 final
你声明该方法不能被覆盖 shadowed/hidden.
虽然不鼓励一口气问3个问题post,但我还是愿意回答的
不能覆盖静态方法,因为这样做没有意义。在你的情况下,如果你想覆盖静态方法,你可以调用该方法并在之后添加你自己的实现,或者你只创建另一个方法。
所以现在你知道静态方法不能被覆盖。但是你在问为什么第三个代码有效?第三个代码是带
的代码
public class 子级扩展父级 {}
对吧?虽然静态方法不能被覆盖,但是可以继承。你正在做的是继承 Parent
所以这完全没问题!
- 现在让我告诉您,在您的第一个代码示例中,您隐藏
Parent
class 中的方法,而不是覆盖。这就是你得到输出的原因。 final
关键字意味着该方法可以 永远不会 被更改,甚至不能隐藏。这就是为什么。
我的理解是静态变量和静态方法属于class,而不是class objects。因此静态方法的 Override
在 Java 中不起作用,至于覆盖我们需要创建一个 class 的实例。但我今天正在尝试一些与我对 Java.
请遵循此代码:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Child ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上实现的输出为:
D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Child
从这个输出我可以了解到,虽然 Child
class 扩展了 Parent
class,但 doit
方法对于每个 class 因为它们是 static
。所以不允许覆盖它们。
现在请按照下面的代码,其中 @Override
添加到 child 的 doIt
方法中:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
@Override // Adding this annotation here
public static void doIt(){
System.out.println("In static method 'doit' of class Child ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上代码的输出给出如下编译错误:
D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:31: error: method does not override or implement a method from a supertype
@Override
^
1 error
这里明确指出注释 Override
不能应用于 static
方法,因为它们不会被覆盖。
现在请按照下面的代码,其中 Child
没有 doIt
方法:
class Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{ /* no doIt method */ }
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
输出为:
D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Parent
为什么上面的代码可以编译运行?我期待 class Child 的方法 doit
的编译错误,我期待 "Method not found"。没看懂。
也请按照下面的代码。这里,Parent
中的 doIt
方法现在是 final
.
class Parent{
public static final void doIt(){ // now final
System.out.println("In static method 'doit' of class Parent ");
}
}
class Child extends Parent{
public static void doIt(){
System.out.println("In static method 'doit' of class Parent ");
}
}
public class StaticPractise{
public static void main(String[] args){
Parent.doIt();
Child.doIt();
}
}
以上代码运行后输出如下:
D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent
public static void doIt(){
^
overridden method is static,final
1 error
D:\Rahul Shivsharan\MyPractise\JAVA>
我所期望的是上面的代码应该可以正常工作,因为 doit
方法在每个 class 中都是静态的,所以即使是 final
关键字也不应该产生任何编译错误因为方法是 static
。
请向我解释方法重写在 Java.
中的静态 classes 中是如何工作的- 静态方法可以重写吗?如果是,那么注释
@Override
怎么会失败? - 如果不能覆盖静态方法,那我的第三个代码块运行怎么没问题?
- 如果不能重写静态方法,那么
final
关键字有何不同?
你搞糊涂了overriding with hiding
首先,这里涉及不同的机制:Overriding and Shadowing (also called hiding)。
1)
静态方法不能被覆盖,因为它们附加到它们在其中定义的 class。但是,您可以 shadow/hide 一个静态方法,就像您对 Parent
/Child
class。这意味着,该方法在 Child
class 中被替换,但在 Parent
class.
当您从那些 classes 的实例调用静态方法时(并且不使用 Class.staticMethod()
调用)。
Parent parent = new Parent();
Child child1 = new Child();
Parent child2 = new Child();
parent.StaticMethod();
child1.StaticMethod();
child2.StaticMethod();
输出是
Static method from Parent
Static method from Child
Static method from Parent
答案是方法的调度。你可以抓住 source code here
2)
调度在 Parent
class 上找到方法。没有动态调度,因为运行时类型用于查找方法句柄。它使用编译时类型。 提醒:从实例调用静态方法被认为是不好的做法,因为像上面这样的事情可能会发生并且很容易被忽视。
3)
使用 final
你声明该方法不能被覆盖 shadowed/hidden.
虽然不鼓励一口气问3个问题post,但我还是愿意回答的
不能覆盖静态方法,因为这样做没有意义。在你的情况下,如果你想覆盖静态方法,你可以调用该方法并在之后添加你自己的实现,或者你只创建另一个方法。
所以现在你知道静态方法不能被覆盖。但是你在问为什么第三个代码有效?第三个代码是带
的代码public class 子级扩展父级 {}
对吧?虽然静态方法不能被覆盖,但是可以继承。你正在做的是继承 Parent
所以这完全没问题!
- 现在让我告诉您,在您的第一个代码示例中,您隐藏
Parent
class 中的方法,而不是覆盖。这就是你得到输出的原因。final
关键字意味着该方法可以 永远不会 被更改,甚至不能隐藏。这就是为什么。