是否可以在派生类中重写静态方法?

时间:2022-06-13 11:00:53

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");
  }
}

7 个解决方案

#1


17  

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

#2


24  

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

instanceMethod() in Bar classMethod() in Foo

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,但是我们创建的实际实例是一个新的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来进行reffered的实例并不重要,编译器只使用声明的引用类型。这就是我们说静态方法没有运行时多态性时的意思。

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),它也不会表现得像一个被覆盖的方法。更多请参考这

#3


4  

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

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

#4


1  

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.

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

#5


0  

No. It's not possible.

不。这是不可能的。

Some similar (not the same) questions here and here.

这里和这里有一些相似的(不相同的)问题。

#6


0  

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.

静态方法在编译时解析。因此,如果您想调用父类方法,那么您应该显式地调用类名或实例,如下所示。

A.foo();

or

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

#7


0  

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()将会抛出编译时错误。

#1


17  

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

#2


24  

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

instanceMethod() in Bar classMethod() in Foo

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,但是我们创建的实际实例是一个新的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来进行reffered的实例并不重要,编译器只使用声明的引用类型。这就是我们说静态方法没有运行时多态性时的意思。

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),它也不会表现得像一个被覆盖的方法。更多请参考这

#3


4  

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

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

#4


1  

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.

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

#5


0  

No. It's not possible.

不。这是不可能的。

Some similar (not the same) questions here and here.

这里和这里有一些相似的(不相同的)问题。

#6


0  

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.

静态方法在编译时解析。因此,如果您想调用父类方法,那么您应该显式地调用类名或实例,如下所示。

A.foo();

or

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

#7


0  

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()将会抛出编译时错误。