Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么';当我试图重写静态方法时,编译器不会抱怨吗?_Java_Static Methods_Overriding - Fatal编程技术网

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()?静态方法不被继承,因此它的

我知道我们不能重写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()

静态方法不被继承,因此它的
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。。。静态方法并不像他在前面的评论中所说的那样被继承。