【问题标题】:Inheriting static methods in Java?在Java中继承静态方法?
【发布时间】:2013-08-04 03:29:25
【问题描述】:

所以我知道,在 Java 中,当您有一个静态方法时,您应该使用 ClassName.method() 格式调用它,而不是使用与实例方法相同的结构,即:

ClassName myObject = new ClassName();
myObject.method();

但是,如果您这样做,它仍然是有效的代码并且可以工作。假设我决定在所讨论的方法是静态的情况下执行此操作,并具有以下设置:

public SuperClass {
    public static int foo(int x) {
        return x;
    }
}

public SubClass extends SuperClass {
    public static int foo(int x) { // Overriding foo() in SuperClass
        return x + 1;
    }
}

public MyDriver {
    public static void main(String[] args) {
        SuperClass myObject = new SubClass(); // Upcasting.
        System.out.println(myObject.foo(5));  // This should polymorphically print 6
    }
}

然而,屏幕上打印出来的是 5 而不是 6。为什么?

【问题讨论】:

    标签: java inheritance polymorphism static-methods


    【解决方案1】:

    静态方法仅适用于定义它们的类,并且不能被覆盖。

    当您调用myObject.foo(5) 时,实际上是在调用SuperClass.foo(5),因为您将myObject 声明为SuperClass,无论您是否将其实例化为一个。

    调用静态方法的正确方法是直接从声明它的类中调用它,所以如果你想调用SubClass.foo(),你必须从显式声明的@中调用它987654326@ 实例(意思是向上转型),或者你需要像这样调用SubClass.foo()

    简单的答案是,从实例调用静态方法的计算结果是从没有实例而不是实例类型的声明类型调用相同的方法。

    我不确定这一点,但如果将代码编译成字节码时,实例静态方法调用实际上会编译成对声明类型的直接调用,我不会感到惊讶。

    编辑:一个赞成票让我重新注意到这一点,我清理了解释以使其更清晰,并修复了我的一些可忽略的语法错误。我希望这对未来的读者有所帮助。

    【讨论】:

      【解决方案2】:

      您应该避免使用类的实例来调用该类的静态方法,因为这会引起混淆。如果您需要以多态方式调用任何方法,请将其设为实例方法。您不能多态地调用静态方法。调用 SuperClass 调用的原因是因为那是 myObject 在编译时的明显类。在以下场景中也可以看到这种效果:

      public void doSomething(SuperClass param) {
          System.out.println("SuperClass");
      }
      
      public void doSomething(SubClass param) {
          System.out.println("SubClass");
      }
      
      public void test() {
          SuperClass myObject = new SubClass();
          doSomething(myObject);
      }
      

      如果 test() 被调用,SuperClass 将被打印出来。

      【讨论】:

        【解决方案3】:

        静态方法不依赖于实例,它们属于类并且只属于类,事实上,如果你有一个静态方法,你总是可以访问一个唯一的实例。

           myObject.foo(5) 
        

        只是一个捷径,你真正在做的是

           SuperClass.foo(5)
        

        【讨论】:

        • 实际上并不是只有一个实例,而是每个虚拟机一个,如果您有多个虚拟机,您可能有多个实例。
        • +1 但根据 ClassLoader 架构,每个 JVM 甚至可能不止一个;以 OSGi 为例。
        【解决方案4】:

        静态方法被 JVM 视为全局方法,它们根本不绑定到对象实例。顺便说一句,您只能重载静态方法,但不能重载。所以检查"Oracle Documentation for Overriding and Hiding Documents"

        定义与超类方法具有相同签名的方法:

        ------------------------------------------超类实例方法超类静态方法   
        子类实例方法 KBD> 覆盖 kBd> 生成编译时错误 kbd>
        子类静态方法 kbd> 生成编译时错误   隐藏                                       

        【讨论】:

          猜你喜欢
          • 2014-03-03
          • 1970-01-01
          • 2011-06-26
          • 1970-01-01
          • 2012-05-04
          • 2012-06-21
          • 2015-03-20
          • 1970-01-01
          相关资源
          最近更新 更多