【问题标题】:Resolving static method at compile-time在编译时解析静态方法
【发布时间】:2013-08-11 11:59:11
【问题描述】:

Java 编译器(几乎)总是在编译时解析静态方法,这是一个普遍的事实。例如:

public class Super {
    static void someMethod() {
        // Do something...
    }
}
public class Derived extends Super {
    // Some other methods, excluding someMethod
}

测试代码:

Derived derived = new Derived();
derived.someMethod();

这应该调用 Super.someMethod(),对吧?它应该在编译时解决,这样javac就会生成invokestatic Super.someMethod,但我看到它会生成invokestatic Derived.someMethod。为什么要这样做?有没有办法以某种方式改变这种行为?

如果我错了,请纠正我。

【问题讨论】:

  • javac 编译器在编译时解析所有 方法引用,以查找方法并检查其签名。然而,当类被 JVM 加载或第一次调用时,方法的实际“绑定”就完成了。
  • (为什么要改变行为?它的工作方式非常有用。)
  • 您的代码甚至无法编译。你是怎么得到那个字节码的?
  • 我已经编辑了代码以反映我对 OP 意图的解释。如果一个类实际上不是从任何东西派生的,那么将其称为“派生”是没有意义的。 @kabbi,请贴出可以编译的代码,以免造成误解。
  • 需要注意的是,使用实例调用静态方法是javac的“swizzle”,它与Java的工作方式没有真正的关系,而纯粹是一种“方便”。编码SomeClass someRef = new SomeClass(); someRef.someStaticMethod(); 完全等同于编码SomeClass.someStaticMethod();。这与继承无关。

标签: java inheritance static-methods


【解决方案1】:

假设在SuperDerived 之间有一个中间超类(例如,称为Intermediate)。

编译器生成Derived.someMethod 的原因是您可能会重新编译Intermediate 以插入someMethod 的实现,这会影响Super 的实现。

【讨论】:

  • 或者您可以简单地编辑并重新编译 Derived 以添加方法。
  • @HotLicks 这并没有说明为什么它会先验地生成Derived.someMethod
  • 它生成的原因是javac从不假设编译时存在的情况就是运行时将存在的情况。当前类之外的任何类都可以更改,并且生成 invokesuper 将导致面对此类更改的不合规行为。
  • @HotLicks 这就是我的回答,具体而言。
  • 是的,我只是指出,除了您所说的适用此概念的场景之外,还有其他场景。
【解决方案2】:

记录在案:

public class TestSuperDerived {
    public static void main(String[] argv) {
        DerivedClass.someMethod();
    }
}
class SuperClass {
    static void someMethod() {
        System.out.println("Here!");
    }
}
class DerivedClass extends SuperClass {
    // Some other methods, excluding someMethod
}

javap 输出:

C:\JavaTools>javap -c TestSuperDerived
Compiled from "TestSuperDerived.java"
public class TestSuperDerived {
  public TestSuperDerived();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2                  // Method DerivedClass.someMethod:()V
       3: return
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    相关资源
    最近更新 更多