【问题标题】:Can I override and overload static methods in Java?我可以在 Java 中覆盖和重载静态方法吗?
【发布时间】:2011-01-29 08:03:49
【问题描述】:

我想知道:

  1. 为什么不能在 Java 中覆盖静态方法?
  2. 可以在 Java 中重载静态方法吗?

【问题讨论】:

    标签: java static overloading overriding


    【解决方案1】:

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

    在实践中,这意味着编译器将在编译时决定执行哪个方法,而不是在运行时决定执行,因为它与重写的实例方法一样。

    请看here

    this 是解释 覆盖 实例方法和 隐藏 类(静态)方法之间区别的 java 文档。

    覆盖: Java 中的覆盖仅仅意味着特定方法将根据对象的运行时类型被调用,并且 不在它的编译时类型上(这是覆盖的情况 静态方法)

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

    【讨论】:

    • 谢谢,您的链接帮助我找到了答案。我在您给定的链接中读到了这一点:“在 Java 中覆盖只是意味着将根据对象的运行时类型而不是根据它的编译时类型调用特定方法(覆盖静态方法就是这种情况)。 "这就是我正在寻找的答案。谢谢。
    • 我在CodeRanch找到了更深入的解释
    • 要真正完成这个答案,您应该回答问题的第二部分。
    【解决方案2】:

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

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

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

    【讨论】:

    • 您能否进一步说明静态方法不能被覆盖,因为没有什么可以覆盖?这样做时有人会得到什么: Class1 c1 = new Class2(); Class2 c2 = new Class2();我是否期望 Class2 中的 Method1() 在这两种情况下都被调用?
    • 静态方法没有什么可以覆盖的,因为静态方法是在编译时链接的,不像普通方法,它的执行是在运行时确定的。你不能指望c1.Method1()c2.Method1() 调用同一个函数,事实上编译器会警告你以这种方式调用静态函数不是明智之举。
    • 如果我仍然感到困惑,请纠正我 - 1. ClassName.methodName() 是在 Java 2 中调用静态方法的最佳实践。在处理静态方法而不是实例化类型时,引用类型很重要 3。我们可以在子类中隐藏静态方法,但不能覆盖,即使代码看起来像是覆盖了方法。
    • 在所有方面都正确。我已经建立了一个小的演示样本here
    • 在 java 中,我们不能将顶级类设为静态。只有嵌套类可以是静态的。上面用户提供的解决方案是完全错误的。
    【解决方案3】:

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

    这就是为什么您在编写时会收到编译器警告

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

    【讨论】:

    • 在 Delphi 中,静态方法可以被覆盖——它们只有指向 VMT 而不是对象实例的指针(上面的示例会调用 MySubClass.myStaticMethod)。
    • 我不认为警告是您回答的有效证据。务实地说,它可以被覆盖并具有与常用方法相同的功能,但我想,中心点将是你拥有(并且没有提供)的“覆盖”的定义。
    • Java 中的方法覆盖(及其与动态调度的联系)是一个非常精确的术语。并且它不能用于静态方法。 @White_King
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        重载也称为静态绑定,所以只要使用静态这个词就意味着静态方法不能显示运行时多态性

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

        对于静态方法,方法调用取决于引用的类型,而不是引用哪个对象,即静态方法只属于一个类而不属于它的实例,因此方法调用是在编译时决定的。

        而在方法重载的情况下静态方法可以被重载 iff它们有不同的参数数量或类型。如果两个方法具有相同的名称和相同的参数列表,那么它们不能仅通过使用 'static' 关键字来定义不同。

        【讨论】:

        • 方法签名是方法名称及其参数的数量、类型和顺序。这意味着即使方法中的参数顺序发生变化,也可以成功重载。
        【解决方案7】:

        如果我使用子类名称 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
            }
        }
        

        【讨论】:

          【解决方案8】:

          静态方法是一种方法,其单一副本由类的所有对象共享。静态方法属于类而不是对象。由于静态方法不依赖于对象,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);
             }
          }
          

          但是在方法覆盖的情况下,超类中的方法和子类中的方法充当不同的方法。超类将拥有自己的副本,子类将拥有自己的副本,因此它不会被方法覆盖。

          【讨论】:

            【解决方案9】:

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

            【讨论】:

              【解决方案10】:
              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 
                  }
              }
              

              这个静态方法覆盖的例子

              注意:如果我们调用带有对象引用的静态方法,那么将调用引用类型(类)静态方法,而不是对象类静态方法。

              静态方法只属于类。

              【讨论】:

              【解决方案11】:

              static 方法是class 级别的方法。

              隐藏概念用于static 方法。

              见:http://www.coderanch.com/how-to/java/OverridingVsHiding

              【讨论】:

                【解决方案12】:

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

                【讨论】:

                  【解决方案13】:

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

                  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 解析的,而不是对象的实际类型。对于非静态,这是正确解决的,因为非静态方法可以覆盖其父方法。

                  【讨论】:

                    【解决方案14】:

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

                    【讨论】:

                      【解决方案15】:

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

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

                      【讨论】:

                        【解决方案16】:

                        其实很容易理解——所有标记为static的东西都只属于类,例如静态方法不能在子类中继承,因为它们属于声明它们的类。参考静态关键字。

                        我发现这个问题的最佳答案是:

                        http://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/

                        【讨论】:

                          【解决方案17】:

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

                          【讨论】:

                            【解决方案18】:

                            来自Why doesn't Java allow overriding of static methods?

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

                            有两个因素推动 Java 的设计影响了这一点。一个是对性能的担忧:有很多批评 Smalltalk 太慢(垃圾收集和多态调用是其中的一部分),Java 的创建者决心避免这种情况。另一个决定是 Java 的目标受众是 C++ 开发人员。使静态方法以它们确实的方式工作有利于 C++ 程序员熟悉,而且速度也非常快,因为无需等到运行时才能确定要调用的方法。

                            【讨论】:

                              【解决方案19】:

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

                              然而,Java 中的静态方法与 Class 而非对象相关联,并在编译时解析和绑定。

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 2011-03-10
                                • 1970-01-01
                                • 2020-12-24
                                • 1970-01-01
                                • 2018-06-19
                                • 2018-08-15
                                • 1970-01-01
                                相关资源
                                最近更新 更多