java 是否可以覆盖派生类中的静态方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2831426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:04:02  来源:igfitidea点击:

Is it possible to override a static method in derived class?

javastatic

提问by MartinDenny2069

I have a static method defined in a base class, I want to override this method in its child class, is it possible?

我在基类中定义了一个静态方法,我想在它的子类中覆盖这个方法,这可能吗?

I tried this but it did not work as I expected. When I created an instance of class B and invoke its callMe() method, the static foo() method in class A is invoked.

我试过这个,但它没有按我预期的那样工作。当我创建类 B 的实例并调用其 callMe() 方法时,会调用类 A 中的静态 foo() 方法。

public abstract class A {
  public static void foo() {
    System.out.println("I am base class");
  }

  public void callMe() {
    foo();
  }
}

Public class B {
  public static void foo() {
      System.out.println("I am child class");
  }
}

回答by Rupesh Yadav

Can I override a static method?

Can I override a static method?

Many people have heard that you can't override a static method. This is true - you can't. However it is possible to write code like this:

很多人都听说过不能覆盖静态方法。这是真的 - 你不能。但是,可以编写如下代码:

class Foo {
    public static void method() {
        System.out.println("in Foo");
    }
}

class Bar extends Foo {
    public static void method() {
        System.out.println("in Bar");
    }
}

This compiles and runs just fine. Isn't it an example of a static method overriding another static method? The answer is no - it's an example of a static method hiding another static method. If you try to override a static method, the compiler doesn't actually stop you - it just doesn't do what you think it does.

这编译并运行得很好。这不是一个静态方法覆盖另一个静态方法的例子吗?答案是否定的——这是一个隐藏另一个静态方法的静态方法的例子。如果您尝试覆盖静态方法,编译器实际上并没有阻止您 - 它只是没有按照您的想法行事。

So what's the difference?

那么有什么区别呢?

Briefly, when you override a method, you still get the benefits of run-time polymorphism, and when you hide, you don't. So what does that mean? Take a look at this code:

简而言之,当您覆盖一个方法时,您仍然可以获得运行时多态性的好处,而当您隐藏时,您则不会。那是什么意思呢?看看这段代码:

class Foo {
    public static void classMethod() {
        System.out.println("classMethod() in Foo");
    }

    public void instanceMethod() {
        System.out.println("instanceMethod() in Foo");
    }
}

class Bar extends Foo {
    public static void classMethod() {
        System.out.println("classMethod() in Bar");
    }

    public void instanceMethod() {
        System.out.println("instanceMethod() in Bar");
    }
}

class Test {
    public static void main(String[] args) {
        Foo f = new Bar();
        f.instanceMethod();
        f.classMethod();
    }
}

If you run this, the output is

如果你运行这个,输出是

instanceMethod() in Bar
classMethod() in Foo

Bar 中的
instanceMethod() Foo 中的 classMethod()

Why do we get instanceMethod from Bar, but classMethod() from Foo? Aren't we using the same instance f to access both of these? Yes we are - but since one is overriding and the other is hiding, we see different behavior.

为什么我们从 Bar 获取 instanceMethod,而从 Foo 获取 classMethod()?我们不是使用同一个实例 f 来访问这两个吗?是的,我们是 - 但由于一个是覆盖的,另一个是隐藏的,我们看到了不同的行为。

Since instanceMethod() is (drum roll please...) an instance method, in which Bar overrides the method from Foo, at run time the JVM uses the actual class of the instance f to determine which method to run. Although f was declared as a Foo, the actual instance we created was a new Bar(). So at runtime, the JVM finds that f is a Bar instance, and so it calls instanceMethod() in Bar rather than the one in Foo. That's how Java normally works for instance methods.

由于 instanceMethod() 是(请打鼓……)一个实例方法,其中 Bar 覆盖了 Foo 中的方法,因此在运行时 JVM 使用实例 f 的实际类来确定要运行的方法。尽管 f 被声明为 Foo,但我们创建的实际实例是一个 new Bar()。所以在运行时,JVM 发现 f 是一个 Bar 实例,所以它调用 Bar 中的 instanceMethod() 而不是 Foo 中的。这就是 Java 通常为实例方法工作的方式。

With classMethod() though. since (ahem) it's a class method, the compiler and JVM don't expect to need an actual instance to invoke the method. And even if you provide one (which we did: the instance referred to by f) the JVM will never look at it. The compiler will only look at the declared type of the reference, and use that declared type to determine, at compile time, which method to call. Since f is declared as type Foo, the compiler looks at f.classMethod() and decides it means Foo.classMethod. It doesn't matter that the instance reffered to by f is actually a Bar - for static methods, the compiler only uses the declared type of the reference. That's what we mean when we say a static method does not have run-time polymorphism.

但是使用 classMethod()。因为(咳咳)它是一个类方法,所以编译器和 JVM 不期望需要一个实际的实例来调用该方法。即使你提供了一个(我们做到了:f 引用的实例),JVM 也永远不会查看它。编译器只会查看引用的声明类型,并在编译时使用该声明类型来确定要调用哪个方法。由于 f 被声明为 Foo 类型,编译器查看 f.classMethod() 并确定它意味着 Foo.classMethod。f 引用的实例实际上是一个 Bar 并不重要 - 对于静态方法,编译器只使用引用的声明类型。这就是我们所说的静态方法没有运行时多态性的意思。

Because instance methods and class methods have this important difference in behavior, we use different terms - "overriding" for instance methods and "hiding" for class methods - to distinguish between the two cases. And when we say you can't override a static method, what that means is that even if you write code that looks like it's overriding a static method (like the first Foo and Bar at the top of this page) - it won't behave like an overridden method. for more refer this

因为实例方法和类方法在行为上有这个重要的区别,所以我们使用不同的术语——实例方法的“覆盖”和类方法的“隐藏”——来区分这两种情况。当我们说您不能覆盖静态方法时,这意味着即使您编写的代码看起来像是覆盖了静态方法(如本页顶部的第一个 Foo 和 Bar) - 它也不会表现得像一个被覆盖的方法。更多参考这个

回答by Artefacto

Static method calls are resolved on compile time (no dynamic dispatch).

静态方法调用在编译时解析(无动态调度)。

class main {
    public static void main(String args[]) {
            A a = new B();
            B b = new B();
            a.foo();
            b.foo();
            a.callMe();
            b.callMe();
    }
}
abstract class A {
    public static void foo() {
        System.out.println("I am superclass");
    }

    public void callMe() {
        foo(); //no late binding here; always calls A.foo()
    }
}

class B extends A {
    public static void foo() {
        System.out.println("I am subclass");
    }
}

gives

I am superclass
I am subclass
I am superclass
I am superclass

回答by Chris Ballance

In Java, static method lookups are determined at compile time and cannot adapt to subclasses which are loaded after compilation.

在 Java 中,静态方法查找是在编译时确定的,不能适应编译后加载的子类。

回答by Ukko

Just to add a why to this. Normally when you call a method the object the method belongs to is used to find the appropriate implementation. You get the ability to override a method by having an object provide it's own method instead of using the one provided by the parent.

只是为了添加一个原因。通常,当您调用方法时,该方法所属的对象用于查找适当的实现。您可以通过让对象提供自己的方法而不是使用父对象提供的方法来覆盖方法。

In the case of static methods there is no object to use to tell you which implementation to use. That means that the compiler can only use the declared type to pick the implementation of the method to call.

在静态方法的情况下,没有对象可以告诉您要使用哪个实现。这意味着编译器只能使用声明的类型来选择要调用的方法的实现。

回答by Phani

Static Methods are resolved at compile time.So if you would like to call parent class method then you should explicitly call with className or instance as below.

静态方法在编译时解析。所以如果你想调用父类方法,那么你应该使用 className 或实例显式调用,如下所示。

A.foo();

or

或者

 A a = new A();
 a.foo();

回答by Pablo Santa Cruz

No. It's not possible.

不,这是不可能的。

Some similar (not the same) questions hereand here.

这里这里有一些类似(不一样)的问题。

回答by Koushik Balaji Venkatesan

In a nutshell static method overriding is not polymorphism it is "method hiding". When you override a static method you will have no access to the base class method as it will be hidden by the derived class.. Usage of super() will throw a compile time error..

简而言之,静态方法覆盖不是多态,而是“方法隐藏”。当您覆盖静态方法时,您将无法访问基类方法,因为它会被派生类隐藏.. 使用 super() 将引发编译时错误..