gpt4 book ai didi

java - 为什么自动装箱会使 Java 中的某些调用模棱两可?

转载 作者:IT老高 更新时间:2023-10-28 20:55:50 26 4
gpt4 key购买 nike

我今天注意到自动装箱有时会导致方法重载解决方案的歧义。最简单的例子似乎是这样的:

public class Test {
static void f(Object a, boolean b) {}
static void f(Object a, Object b) {}

static void m(int a, boolean b) { f(a,b); }
}

编译时出现如下错误:

Test.java:5: reference to f is ambiguous, both method
f(java.lang.Object,boolean) in Test and method
f(java.lang.Object,java.lang.Object) in Test match

static void m(int a, boolean b) { f(a, b); }
^

这个错误的修复很简单:只需使用显式自动装箱:

static void m(int a, boolean b) { f((Object)a, b); }

按预期正确调用第一个重载。

那么为什么重载解析失败了?为什么编译器不自动装箱第一个参数,并正常接受第二个参数?为什么我必须明确请求自动装箱?

最佳答案

当您自己将第一个参数强制转换为 Object 时,编译器将匹配该方法而不使用自动装箱(JLS3 15.12.2):

The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

如果你不显式地强制转换,它会进入第二阶段,试图找到匹配的方法,允许自动装箱,然后确实是模棱两可,因为你的第二个参数可以通过 boolean 值或对象匹配。

The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation.

为什么在第二阶段,编译器不选择第二种方法,因为不需要对 boolean 参数进行自动装箱?因为在找到这两种匹配方法后,仅使用子类型转换来确定这两种方法中最具体的方法,而不管最初为匹配它们而发生的任何装箱或拆箱(第 15.12.2.5 节)。

另外:编译器不能总是根据需要的自动(取消)装箱次数选择最具体的方法。它仍然可能导致模棱两可的情况。例如,这仍然是模棱两可的:

public class Test {
static void f(Object a, boolean b) {}
static void f(int a, Object b) {}

static void m(int a, boolean b) { f(a, b); } // ambiguous
}

请记住,用于选择匹配方法的算法(编译时步骤 2)是固定的,并在 JLS 中进行了描述。一旦进入第 2 阶段,就没有选择性的自动装箱或拆箱。编译器将定位 所有 可访问的方法(这两种情况下的两种方法)和适用的方法(同样是两种方法),然后才选择最具体的方法而不查看装箱/拆箱,即这里有歧义。

关于java - 为什么自动装箱会使 Java 中的某些调用模棱两可?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/501412/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com