为什么在JAVA中的编译时必须完成方法重载解析?

时间:2018-10-28 06:29:30

标签: java jvm

这是一个简单的代码块:

lastBreakIndex + (unallocatedValuesCount / remainingPartitions)

对于我们知道的方法调用public class CYoungMan extends YoungMan{ @Override public String meet(Object obj) { return obj.getClass().getSimpleName(); } @Override public String meet(String str) { return "String class"; } public static void main(String[] args) throws Throwable { Object str = "katie"; YoungMan ym = new CYoungMan(); ym.meet(str); } }

  1. 编译器确定由类ym.meet(str)和方法YoungMan组合而成的符号引用;
  2. 然后,在运行时中,JVM按String meet(Object obj)的运行时类型及其继承层次结构定位方法块。

我的问题是,为什么不采用(1)在运行时中实现,而我们按参数的运行时类型来定位重载方法?

我更关心的是,为什么Java设计人员决定这样做(如我在(1)和(2)中所述),又为什么不在运行时中选择“ Multiple dispatch”(如“我的建议”)?有官方解释吗?

2 个答案:

答案 0 :(得分:2)

简短的版本是因为这是Java系统决定执行此操作的方式(此外,它在运行时速度要快得多)。 Groovy(在其他JVM语言中)可以进行动态调度,并且invokedynamic已添加到Java 7的JVM指令集中,以帮助使这种方法更加有效。

答案 1 :(得分:1)

尽管重载的方法在代码中具有相同的名称,但具有n重载的方法将具有n个不同的方法签名。这些方法可以接受并返回不同的参数和返回值。编译器需要知道使用哪个方法签名,以了解其编译的代码是否有效。

考虑以下重载方法:

class Translator {
    String translate(int i) { return String.valueOf(i); }
    int translate(String s) { return Integer.valueOf(s); }
}

这些方法使用相同的名称,但签名却大不相同。如果要选择一个而不是另一个,那么最终可能会得到无效的可执行文件。

另一方面,重写的方法共享相同的签名。由于它们具有相同的输入类型和返回类型,因此可以在运行时选择实现,同时仍然确保编译时的安全性。

选择重载方法不会导致性能下降。经过编译时间后,调用一个重载方法与另一个重载方法的成本与调用具有单独名称的方法完全相同。调用虚拟方法已经很昂贵了,向过程中添加参数解析只会进一步降低执行速度。