【问题标题】:Static method override静态方法覆盖
【发布时间】:2011-05-16 05:39:59
【问题描述】:
class XYZ{
    public static void show(){
        System.out.println("inside XYZ");
    }
}

public class StaticTest extends XYZ {
    public static void  show() {
        System.out.println("inside statictest");

    }

    public static void main(String args[]){
        StaticTest st =new StaticTest();
        StaticTest.show();

    }

}

虽然我们知道静态方法不能被覆盖。那么究竟发生了什么?

【问题讨论】:

    标签: java oop inheritance polymorphism static-methods


    【解决方案1】:

    静态方法属于该类。它们不能被覆盖。但是,如果在子类中定义了与父类静态方法具有相同签名的方法,则它隐藏父类方法。 StaticTest.show() 隐藏了 XYZ.show() 方法,因此 StaticTest.show() 是在代码中的 main 方法中执行的方法。

    【讨论】:

    • 这是一个更好的答案,因为正如您所说,它们不是完全独立的方法。因此,子类中的 hiding 方法必须具有相同或更少限制的可见性。
    • @John Lehmann:为什么子类中的隐藏方法必须具有相同或限制性的可见性?
    【解决方案2】:

    不是overriding,它们是两个不同类中具有相同签名的两种不同方法。但是来自XYZ 的方法不能通过继承在子类中使用。

    它将调用来自StaticTest的方法

    【讨论】:

      【解决方案3】:

      它没有被正确地覆盖......静态方法被“绑定”到类,所以

      StaticTest.show();
      

      XYZ.show();
      

      是两个完全不同的东西。注意你不能调用 super.show()

      【讨论】:

        【解决方案4】:

        要查看差异,您必须使用更强大的示例:

        class Super {
            public static void hidden(Super superObject) {
                System.out.println("Super-hidden");
                superObject.overriden();
            }
        
            public void overriden() {
                System.out.println("Super-overriden");
            }
        }
        
        class Sub extends Super {
            public static void hidden(Super superObject) {
                System.out.println("Sub-hidden");
                superObject.overriden();
            }
        
            public void overriden() {
                System.out.println("Sub-overriden");
            }
        }
        
        public class Test {
            public static void main(String[] args) {
                Super superObject = new Sub();
                superObject.hidden(superObject);
            }
        }
        

        由于Samit G. 已经在基类和派生类中编写了具有相同签名的静态方法,因此隐藏了实现,这是不可覆盖的。您可以通过将一个或另一个静态方法更改为非静态方法或将它们都更改为非静态来查看 java 编译器出现的编译错误是什么。

        【讨论】:

        • 使用静态方法来自声明的类型Super,这里),即使superObject持有的实例的实际类型有它自己的静态方法具有相同的签名
        【解决方案5】:

        这不是一个覆盖,而是一个单独的方法,将XYZ中的方法隐藏起来。

        【讨论】:

          【解决方案6】:

          据我所知,任何静态成员(方法或状态)都是类的属性,不会与类的任何实例相关联。因此,在您的示例中,XYZ 是一个类,StaticTest 也是如此(如您所知)。因此,通过调用构造函数,首先会发生两件事。创建了一个 Class 类型的 Object。它有一个成员调用显示()。类,XYZ.class,从 Object 扩展,所以它上面有所有这些 Object 方法加上 show()。与 StaticClass 相同,类对象上也有 show()。不过,它们都扩展了 java.lang.Object。 StaticClass 的实例也是 XYZ 的实例。然而现在更有趣的问题是当你在 st 上调用 show() 时会发生什么?

          StaticClass st = new StaticClass();
          st.show();
          XYZ xyz = st;
          xyz.show();
          

          那里会发生什么?我的猜测是第一次是 StaticClass.show(),第二次是 XYZ.show()。

          【讨论】:

            【解决方案7】:

            静态方法与类而非实例(对象)相关联。

            因此调用总是 ClassName.staticMethod();

            当子类中出现相同静态方法的这种情况时,称为精炼(重新定义)静态方法,而不是覆盖。

            【讨论】:

              【解决方案8】:

              // Java 允许从实例/对象引用中调用静态方法 // 这在其他纯 OOP 语言(如 C# Dot net)中并非如此。 // 这会导致这种混乱。 // 从技术上讲,静态方法总是绑定到类而不是实例。 // 换句话说,绑定是在静态函数的编译时进行的。 - 早期绑定 // // 例如。

              class BaseClass 
              {
               public static void f1()
               {
                System.out.println("BaseClass::f1()...");
               } // End of f1().
              }
              
              public class SubClass extends BaseClass 
              {
                public static void f1() 
                {
                  System.out.println("SubClass::f1()...");
                  // super.f1(); // non-static variable super cannot be referenced from a static context
              
                } // End of f1().
              
                public static void main(String[] args)
                {
              f1();
              SubClass obj1 = new SubClass();
              obj1.f1();
              BaseClass b1 = obj1;
              b1.f1();
              
                } // End of main().
              
              } // End of class.
              
              // Output:
              // SubClass::f1()...
              // SubClass::f1()...
              // BaseClass::f1()...
              

              // // // 所以即使在这种情况下,使用实例 b1 调用,它实际上是指 // SuperClass 类型的对象,它调用 BaseClass:f1 方法。 //

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2018-06-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-01-04
                • 2010-10-27
                相关资源
                最近更新 更多