JVM如何在函数重载的情况下找到要调用的方法(具有最接近匹配的参数)

swa*_*apy 12 java types jvm overloading

JVM决定在编译时调用哪个重载方法.我有一个例子:

public class MainClass{

  public static void go(Long n) {System.out.println("takes Long ");}
  public static void go(Short n) {System.out.println("takes Short ");}
  public static void go(int n) {System.out.println("takes int ");}

  public static void main(String [] args) {
    short y = 6;
    long z = 7;
    go(y);
    go(z);
    go((Short)y);
  }
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解,它应该打印以下内容:

takes Short
takes Long
takes Short
Run Code Online (Sandbox Code Playgroud)

...但实际输出是:

takes int
takes Long
takes Short
Run Code Online (Sandbox Code Playgroud)

但是,如果我有以下三个功能:

public static void go(Integer n) {System.out.println("takes Integer");}
public static void go(Long n) {System.out.println("takes Long ");}
public static void go(Short n) {System.out.println("takes Short ");}
Run Code Online (Sandbox Code Playgroud)

...并使用以下方式调用它:

int a= 10; and go(i);  //output : takes Integer.
Run Code Online (Sandbox Code Playgroud)

...为什么shortint?有区别?

Roh*_*ain 18

有关规则,请参阅JLS第15.12.2节,以确定要调用的方法.如果方法重载,编译器总是选择最具体的方法:

可能存在多于一种这样的方法,在这种情况下,选择最具体的方法.最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法.

编译器首先尝试在没有装箱或取消装箱的情况下解决方法,如下所示:

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用.如果在此阶段没有找到适用的方法,则处理继续到第二阶段.

强调我的.

所以,在你的第一个代码中,short可以用作int类型参数的参数.编译器不会使用带参数的方法Short,因为这需要装箱.虽然在long类型的情况下,因为它不能用作int类型的参数,所以它用于装箱Long.记住加宽比拳击更受欢迎.

在你的2 ,还有比拳击没有其他的办法intInteger.所以,它用Integer参数调用方法.


Jon*_*eet 8

JVM根本找不到它.编译器.它根据JLS第15.12.2.5节中的规则选择最具体的方法:

如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符.Java编程语言使用选择最具体方法的规则.

非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个没有编译时类型错误的调用,那么一个方法比另一个方法更具体.

......(完整规则)......

  • +1不仅名称和参数类型必须完全匹配,但返回类型也必须如此.如果您调用B并且在不重新编译A的情况下更改B中方法的返回类型,则无法在运行时找到该方法. (2认同)