为什么自动装箱在Java中使一些调用变得模棱两可?
我今天注意到,自动装箱有时会导致方法重载解析的模糊性。最简单的例子如下:为什么自动装箱在Java中使一些调用变得模棱两可?,java,compiler-construction,overloading,autoboxing,Java,Compiler Construction,Overloading,Autoboxing,我今天注意到,自动装箱有时会导致方法重载解析的模糊性。最简单的例子如下: 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, bot
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,它也会起作用。当您说f(a,b)时,编译器不知道应该引用哪个函数
这是因为a是int,但f中预期的参数是对象。因此,编译器决定将a转换为对象。现在的问题是,如果a可以转换为对象,那么b也可以
这意味着函数调用可以引用任一定义。这使得通话模棱两可
当您手动将a转换为对象时,编译器只会查找最接近的匹配项,然后引用它
为什么编译器没有选择
通过“执行”可以实现的功能
最小可能数量的
装箱/取消装箱转换“
请参见以下案例:
f(boolean a, Object b)
f(Object a , boolean b)
如果我们调用likef(布尔a,布尔b),它应该选择哪个函数?这是矛盾的,对吗?类似地,当存在大量争论时,这将变得更加复杂。所以编译器选择给你一个警告
由于无法知道程序员真正想要调用哪一个函数,编译器会给出一个错误。当你说f(a,b)时,编译器会对应该引用哪个函数感到困惑
这是因为a是int,但f中预期的参数是对象。因此,编译器决定将a转换为对象。现在的问题是,如果a可以转换为对象,那么b也可以
这意味着函数调用可以引用任一定义。这使得通话模棱两可
当您手动将a转换为对象时,编译器只会查找最接近的匹配项,然后引用它
为什么编译器没有选择
通过“执行”可以实现的功能
最小可能数量的
装箱/取消装箱转换“
请参见以下案例:
f(boolean a, Object b)
f(Object a , boolean b)
如果我们调用likef(布尔a,布尔b),它应该选择哪个函数?这是矛盾的,对吗?类似地,当存在大量争论时,这将变得更加复杂。所以编译器选择给你一个警告
由于没有办法知道程序员真正想要调用哪一个函数,编译器给出了一个错误。编译器没有自动将第一个参数设为框。一旦这样做了,第二个参数是不明确的,因为它可以被视为布尔或对象
解释自动装箱和选择要调用的方法的规则。编译器首先尝试在不使用任何自动装箱的情况下选择一个方法,因为装箱和取消装箱会带来性能损失。如果在不使用装箱的情况下无法选择任何方法,如本例中所示,则装箱在该方法的所有参数的表上。编译器确实自动装箱了第一个参数。一旦这样做了,第二个参数是不明确的,因为它可以被视为布尔或对象
解释自动装箱和选择要调用的方法的规则。编译器首先尝试在不使用任何自动装箱的情况下选择一个方法,因为装箱和取消装箱会带来性能损失。如果在不使用装箱的情况下无法选择任何方法(如本例所示),则该方法的所有参数都将使用装箱。请参阅 cast很有帮助,因为这样就不需要装箱来找到要调用的方法。如果没有强制转换,第二次尝试是允许装箱,然后也可以装箱布尔值 与其让人们猜测,不如有清晰易懂的规格说明会发生什么。参见 cast很有帮助,因为这样就不需要装箱来找到要调用的方法。如果没有强制转换,第二次尝试是允许装箱,然后也可以装箱布尔值
最好有清晰易懂的规范来说明将发生什么,而不是让人们猜测。当您将第一个参数转换为对象时,编译器将匹配该方法,而不使用自动装箱(JLS3 15.12.2): 第一阶段(§15.12.2.2)执行 未经允许的过载解决方案 装箱或取消装箱转换,或 变量算术方法的使用 调用。如果没有适用的方法 在这个阶段发现的 处理继续到第二级 阶段 如果你不显式地释放它,它将进入第二阶段,试图找到匹配的冰毒