我可以覆盖和重载Java中的静态方法吗?


Answers:


98

静态方法不能完全按字面意思覆盖,但是它们可以隐藏父级静态方法

在实践中,这意味着编译器将决定在编译时而不是在运行时执行哪个方法,这与覆盖实例方法一样。

举个漂亮的例子,在这里看看。

是Java文档解释之间的区别重写实例方法和隐藏的类(静态)方法。

覆盖:在Java中,覆盖只是意味着将根据对象的运行时类型而不是对象的编译时类型来调用特定方法(对于覆盖的静态方法就是这种情况)

隐藏:静态的父类方法不属于子类(尽管它们是可访问的),因此没有覆盖它的问题。即使您在子类中添加了与其父类中相同的另一个静态方法,该子类静态方法也是唯一的,并且不同于其父类中的静态方法。


2
谢谢,您的链接帮助我找到了答案。我在给定的链接中读到了这一点:“ Java中的覆盖只是意味着将根据对象的运行时类型而不是对象的编译时类型来调用特定方法(对于覆盖的静态方法就是这种情况)。 ” 这就是我一直在寻找的答案。谢谢。
Mital Pritmani 2011年

2
我在CodeRanch
2014年

为了使此答案真正完成,您可能应该回答问题的第二部分。
Tim M.

29

静态方法不能被覆盖,因为没有什么可以覆盖的,因为它们将是两个不同的方法。例如

static class Class1 {
    public static int Method1(){
          return 0;
    }
}
static class Class2 extends Class1 {
    public static int Method1(){
          return 1;
    }

}
public static class Main {
    public static void main(String[] args){
          //Must explicitly chose Method1 from Class1 or Class2
          Class1.Method1();
          Class2.Method1();
    }
}

是的,静态方法可以像任何其他方法一样重载。


2
您能否更多地介绍不能重写的静态方法,因为没有什么可以重写的?有人这样做会得到什么:Class1 c1 = new Class2(); Class2 c2 =新的Class2(); 我期望在两种情况下都调用Class2的Method1()还是不调用?
realPK 2014年

静态方法没有要重写的地方,因为静态方法是在编译时链接的,这与普通方法不同,普通方法的执行是在运行时确定的。您不能期望c1.Method1()c2.Method1()调用相同的函数,实际上,编译器会警告您以这种方式调用静态函数并不是一件明智的事情。
VolatileDream

如果我仍然很困惑,请指正我-1. ClassName.methodName()是在Java中调用静态方法的最佳实践2.处理静态方法时引用类型很重要,而不是实例化类型3.可以在子类中隐藏静态方法,但是即使代码看起来像是重写方法,也不能重写。
realPK 2014年

正确无误。我已经把一个小演示样品在这里
VolatileDream

1
在Java中,我们不能将顶级类设为静态。只有嵌套类可以是静态的。上面的用户提供的解决方案是完全错误的。
user1001

16

静态方法不能被覆盖,因为静态方法不会在运行时在对象实例上分派。编译器决定调用哪个方法。

这就是为什么在编写时收到编译器警告的原因

 MyClass myObject = new MyClass();
 myObject.myStaticMethod();
 // should be written as
 MyClass.myStaticMethod()
 // because it is not dispatched on myObject
 myObject = new MySubClass();
 myObject.myStaticMethod(); 
 // still calls the static method in MyClass, NOT in MySubClass

静态方法可以重载(这意味着您可以为多个方法使用相同的方法名称,只要它们具有不同的参数类型即可)。

 Integer.parseInt("10");
 Integer.parseInt("AA", 16);

1
在Delphi中,可以重写静态方法-它们仅具有指向VMT的指针,而不是对象实例(并且上面的示例将调用MySubClass.myStaticMethod)。
哈。

8

静态的父类方法不属于子类(尽管它们是可访问的),因此没有覆盖它的问题。即使您在子类中添加与其父类中相同的另一个静态方法,该子类静态方法也是唯一的,并且不同于其父类中的静态方法。


4

静态方法不能被覆盖,因为它们不是对象状态的一部分。相反,它们属于类(即它们是类方法)。可以重载静态(和最终)方法。


3

如果我通过使用SubClass名称MysubClass来调用方法,则子类方法将显示静态方法可以被覆盖还是不能被覆盖

class MyClass {
    static void myStaticMethod() {
        System.out.println("Im in sta1");
    }
}

class MySubClass extends MyClass {

    static void  myStaticMethod() {
        System.out.println("Im in sta123");
    }
}

public class My {
    public static void main(String arg[]) {

        MyClass myObject = new MyClass();
        myObject.myStaticMethod();
        // should be written as
        MyClass.myStaticMethod();
        // calling from subclass name
        MySubClass.myStaticMethod();
        myObject = new MySubClass();
        myObject.myStaticMethod(); 
        // still calls the static method in MyClass, NOT in MySubClass
    }
}

3

静态方法是由类的所有对象共享单个副本的方法。静态方法属于类而不是对象。由于静态方法不依赖于对象,因此Java编译器无需等到对象创建。因此要调用静态方法,我们使用ClassName.method()之类的语法;

在方法重载的情况下,方法应在同一类中进行重载。即使将它们声明为静态方法,也可以将其重载为,

   Class Sample
    {
         static int calculate(int a,int b,int c)
           {
                int res = a+b+c;
                return res;
           }
           static int calculate(int a,int b)
           {
                int res = a*b;
                return res;
           }
}
class Test
{
   public static void main(String []args)
   {
     int res = Sample.calculate(10,20,30);
   }
}

但是在方法重载的情况下,超类中的方法和子类中的方法充当不同的方法。超类将具有自己的副本,子类将具有自己的副本,因此不会受到方法覆盖。


3

重载也称为静态绑定,因此一旦使用单词static,就意味着静态方法无法显示运行时多态性

我们无法覆盖静态方法,但是在超类及其子类中存在相同静态方法的不同实现是有效的。只是派生类将隐藏基类的实现。

对于静态方法,方法调用取决于引用的类型,而不取决于引用的对象,即静态方法仅属于类而不是其实例,因此,方法调用是在编译时自行决定的。

在方法重载的情况下,静态方法可以重载, 前提是它们具有diff数量或参数类型。如果两个方法具有相同的名称和相同的参数列表,则只能通过使用'static'关键字将它们定义为不同的值。


方法签名是方法名称及其参数的数量,类型和顺序。这意味着即使方法中参数的顺序更改了,也可以成功重载。
iCantC

2

不可以,静态方法不能被覆盖,因为它是类而不是对象的一部分。但是一个可以重载静态方法。



1
class SuperType {

    public static void  classMethod(){
        System.out.println("Super type class method");
    }
    public void instancemethod(){
        System.out.println("Super Type instance method");
    }
}


public class SubType extends SuperType{


    public static void classMethod(){
        System.out.println("Sub type class method");
    }
    public void instancemethod(){
        System.out.println("Sub Type instance method");
    }
    public static void main(String args[]){
        SubType s=new SubType();
        SuperType su=s;
        SuperType.classMethod();// Prints.....Super type class method
        su.classMethod();   //Prints.....Super type class method
        SubType.classMethod(); //Prints.....Sub type class method 
    }
}

此示例覆盖静态方法

注意:如果我们使用对象引用调用静态方法,则将调用引用类型(类)静态方法,而不是对象类静态方法。

静态方法仅属于类。


静态方法不会 被覆盖,它们会被隐藏。有关更多信息,请访问docs.oracle.com/javase/tutorial/java/IandI/override.html
Pshemo

0

使用静态方法的真正目的是在不创建类实例的情况下访问类的方法。如果我们重写该方法没有任何意义,因为它们将由classname.method()访问


0

不可以,您不能覆盖静态方法。静态对象针对类而不是实例进行解析。

public class Parent { 
    public static String getCName() { 
        return "I am the parent"; 
    } 
} 

public class Child extends Parent { 
    public static String getCName() { 
        return "I am the child"; 
    } 
} 

每个类都有一个静态方法getCName()。当您调用类名称时,它的行为与预期的一样,并且每个函数都返回预期的值。

@Test 
public void testGetCNameOnClass() { 
    assertThat(Parent.getCName(), is("I am the parent")); 
    assertThat(Child.getCName(), is("I am the child")); 
} 

在这个单元测试中没有任何惊喜。但这并不能覆盖,它声明了名称冲突。

如果我们尝试从类的实例中获取静态信息(不是一个好习惯),那么它实际上表明:

private Parent cp = new Child(); 
`enter code here`
assertThat(cp.getCName(), is("I am the parent")); 

即使cp是Child,也可以通过声明的类型Parent解析静态变量,而不是通过对象的实际类型解析。对于非静态方法,这可以正确解决,因为非静态方法可以覆盖其父方法。


0

您可以重载静态方法,但不能覆盖静态方法。实际上,您可以在子类中重写静态方法,但这不称为重写,因为重写应该与多态性和动态绑定有关。静态方法属于该类,因此与这些概念无关。静态方法的重写更像是一个阴影。


0

我设计了一个静态方法覆盖的代码。我认为它很容易覆盖。请向我说明它如何无法覆盖静态成员。这是我的代码-

class Class1 {
    public static int Method1(){
          System.out.println("true");
          return 0;
    }
}
class Class2 extends Class1 {
    public static int Method1(){
   System.out.println("false");
          return 1;
    }

}
public class Mai {
    public static void main(String[] args){
           Class2 c=new Class2();
          //Must explicitly chose Method1 from Class1 or Class2
          //Class1.Method1();
          c.Method1();
    }
}


0

由于任何静态方法都是类的一部分而不是实例的一部分,因此无法覆盖静态方法


0

为什么不是Java允许的静态方法覆盖?

覆盖取决于拥有类的实例。多态性的重点是您可以对一个类进行子类化,并且实现那些子类的对象对于在超类中定义的相同方法(在子类中被重写)将具有不同的行为。静态方法不与类的任何实例关联,因此该概念不适用。

影响Java设计的因素有两个。一个是对性能的关注:Smalltalk对其速度太慢提出了很多批评(垃圾回收和多态调用是其中的一部分),Java的创建者决心避免这种情况。另一个决定是Java的目标受众是C ++开发人员。使静态方法按其实际方式工作对C ++程序员来说是个好处,而且速度非常快,因为不需要等到运行时就确定要调用哪个方法。


-1

绝对不能在Java中覆盖静态方法。因为JVM在运行时通过使用Java中的动态绑定来基于对象解析正确的重写方法。

但是,Java中的静态方法与Class关联,而不是与对象关联,并且在编译时进行解析和绑定。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.