34

我知道我们不能覆盖 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()");
    }
}

我如何能够覆盖a()类中的方法B

4

9 回答 9

54

You didn't override anything here. To see for yourself, Try putting @Override annotation before public static void a() in class B and Java will throw an error.

You just defined a function in class B called a(), which is distinct (no relation whatsoever) from the function a() in class A.

But Because B.a() has the same name as a function in the parent class, it hides A.a() [As pointed by Eng. Fouad]. At runtime, the compiler uses the actual class of the declared reference to determine which method to run. For example,

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.

You cannot override static methods in Java. Remember static methods and fields are associated with the class, not with the objects. (Although, in some languages like Smalltalk, this is possible).

I found some good answers here: Why doesn't Java allow overriding of static methods?

于 2013-05-17T20:33:52.747 回答
9

这就是所谓的hiding a method,如 Java 教程Overriding and Hiding Methods中所述:

如果子类定义了与超类中的类方法具有相同签名的类方法,则子类中的方法会隐藏超类中的方法。

于 2013-05-17T20:35:46.287 回答
6

static methods are not inherited so its B's separate copy of method

static are related to class not the state of Object

于 2013-05-17T20:32:33.457 回答
3

You didn't override the method a(), because static methods are not inherited. If you had put @Override, you would have seen an error.

A.java:10: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error

But that doesn't stop you from defining static methods with the same signature in both classes.

于 2013-05-17T20:33:14.093 回答
2

此外,调用方法的选择取决于变量的声明类型。

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()被调用。

于 2013-05-17T20:38:58.540 回答
1

您的方法不是被覆盖的方法。您只是尝试在派生类中的方法之前放置 @Override 注释。它会给你一个编译时错误。所以java不允许你覆盖静态方法。

于 2014-05-23T04:17:08.927 回答
1

虽然 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。

于 2016-09-27T12:50:53.373 回答
0

静态方法将通过其类名调用,因此我们不需要创建类对象,我们只需使用类名调用它,因此我们不能覆盖静态

例如

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();

意味着静态类如果被覆盖则不能被覆盖,那么如何调用它。

于 2015-03-04T16:54:17.150 回答
0

静态成员属于类而不属于任何对象。因此静态方法不能被覆盖。覆盖也发生在运行时,因此编译器不会抱怨。

但是,您可以将 @Override 注释添加到方法中。这将标记编译器错误。

于 2021-10-13T14:06:56.983 回答