Java 为什么';当我试图重写静态方法时,编译器不会抱怨吗?
我知道我们不能重写Java中的静态方法,但是有人能解释一下下面的代码吗Java 为什么';当我试图重写静态方法时,编译器不会抱怨吗?,java,static-methods,overriding,Java,Static Methods,Overriding,我知道我们不能重写Java中的静态方法,但是有人能解释一下下面的代码吗 class A { public static void a() { System.out.println("A.a()"); } } class B extends A { public static void a() { System.out.println("B.a()"); } } 我如何能够在类B中重写方法a()?静态方法不被继承,因此它的
class A {
public static void a() {
System.out.println("A.a()");
}
}
class B extends A {
public static void a() {
System.out.println("B.a()");
}
}
我如何能够在类
B
中重写方法a()
?静态方法不被继承,因此它的B
方法的单独副本
静态
与类
相关,而不是对象的状态
您没有重写方法a()
,因为静态
方法没有继承。如果您放置了@Override
,您将看到一个错误
A.java:10: error: method does not override or implement a method from a supertype
@Override
^
1 error
但这并不能阻止您在两个类中定义具有相同签名的静态方法。您在这里没有重写任何内容。要亲自查看,请尝试将@Override
注释放在类B
中的publicstaticvoida()
之前,Java将抛出一个错误
A.java:10: error: method does not override or implement a method from a supertype
@Override
^
1 error
您刚刚在类B
中定义了一个名为a()
的函数,它与类a
中的函数a()
不同(没有任何关系)
但是因为B.a()
与父类中的函数同名,所以它隐藏了a.a()
[正如Eng.Fouad所指出的那样]。在运行时,编译器使用声明引用的实际类来确定要运行的方法。比如说,
B b = new B();
b.a() //prints B.a()
A a = (A)b;
a.a() //print A.a(). Uses the declared reference's class to find the method.
不能在Java中重写静态方法。记住static
方法和字段与类关联,而不是与对象关联。(尽管在一些语言中,如Smalltalk,这是可能的)
我在这里找到了一些很好的答案:这被称为隐藏方法,如Java教程中所述:
如果子类定义的类方法与
类中的方法,子类中的方法隐藏
超类中的一个
此外,要调用的方法的选择取决于声明的变量类型
B b = null;
b.a(); // (1) prints B.a()
A a = new B();
a.a(); // (2) prints a.a()
在(1)处,如果系统关心b
的身份,它将抛出一个NPE
。在(2)处,忽略a
的值。由于a
被声明为a
,因此将调用a.a()
。您的方法不是重写方法。您只需在派生类中将@Override注释放在方法之前。它将给您一个编译时错误。所以java将不允许您重写静态方法。静态方法将通过其类名调用,因此我们不需要创建类对象,我们只需使用类名对其进行调用,因此我们无法重写静态方法
比如说
class AClass{
public static void test(){
}
}
class BClass extends AClass{
public static void test(){}
}
class CClass extends BClass{
public static void main(String args[]){
AClass aclass=new AClass();
aclass.test(); // its wrong because static method is called
// by its class name it can't accept object
}
}
我们就叫它
AClass.test()代码>
表示无法重写静态类
如果它被覆盖,那么如何校准它。当goblinjuice的答案被接受时,我认为示例代码可以改进:
public class StaticTest {
public static void main(String[] args) {
A.print();
B.print();
System.out.println("-");
A a = new A();
B b = new B();
a.print();
b.print();
System.out.println("-");
A c = b;
c.print();
}
}
class A {
public static void print() {
System.out.println("A");
}
}
class B extends A {
public static void print() {
System.out.println("B");
}
}
产生:
A
B
-
A
B
-
A
如果B重写了print()
,它会在最后一行写B。,因为您没有这样做<代码>B.a()
只能通过类B
访问。如果您有类似于A A=newb();a、 a()代码>,它将打印“A.A()”,即使它是类型B。如果它确实被重写,那么它将打印“B.A()”。请注意,Java的奇特特性允许您从对象实例调用静态方法,这有助于在这里散播混乱。是什么让您认为您在B
中覆盖了a
?您可以通过在该方法之前添加@Override
注释来轻松测试。如果从B
中删除a()
函数,则可以测试a()
是否被B
继承。它确实继承,但不重写。相反,如果您在B
中声明另一个a()
函数,它将隐藏a()
@Dorus dlev now under。谢谢你,嗯。。。不确定这是否是方法隐藏。A
和B
都有static A()
,编译器将根据声明的引用类型查找并调用正确的函数。例如,A A=新B();a、 a()//打印A.A(),因为编译器查看A的声明引用,A是@goblinjuice在B
中声明A()
将从B
@goblinjuice隐藏A()
,这是Java中隐藏的字面定义。但是,您不应该在类实例上调用静态方法。True。但这是展示这种特殊行为的方式。“您可以在null
上调用方法?真的吗?”您声称静态方法不会被继承,但如果我从B
中删除a()
,那么B.a()代码>突然打印“A.A()”。您可以继承静态方法,但不能重写它们。相反,你把它们藏起来,就像英格·福阿德在他的回答中提到的那样。@Dorus在任何地方都没有看到提到遗产!确实没有提到继承,但是在编辑之前,这个答案使它看起来像静态方法,没有继承,或者至少是不完整的。这是错误的,你继承了静态方法,但在子类中声明另一个具有相同签名的方法的机制称为隐藏,其工作原理与重写略有不同。如何继承静态方法@Dorus?+1 for@Dorus。。。静态方法并不像他在前面的评论中所说的那样被继承。