为什么自动装箱会使 Java 中的某些调用变得不明确?

2023-12-02

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

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):

第一阶段(§15.12.2.2)执行 未经允许的重载解析 装箱或拆箱转换,或者 使用可变数量方法 调用。如果没有适用的方法 然后在这个阶段发现 处理继续到第二个 阶段。

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

第二阶段(§15.12.2.3)执行 重载解析同时允许 装箱和拆箱,但仍然 排除使用变量数量 方法调用。

为什么在第二阶段编译器不选择第二种方法,因为不需要对布尔参数进行自动装箱?因为在找到两个匹配方法之后,仅使用子类型转换来确定这两个方法中最具体的方法,而不管首先发生的任何装箱或拆箱以匹配它们(第 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 阶段,就不再有选择性的自动装箱或拆箱。编译器会定位到all可以访问的方法(在这些情况下是两种方法)和适用的方法(同样是两种方法),然后才选择最具体的一种而不考虑装箱/拆箱,这在这里是不明确的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么自动装箱会使 Java 中的某些调用变得不明确? 的相关文章

随机推荐

  • 如何使用 jQuery 获取整个页面的 HTML?

    I used document html 但这引发了错误 有没有办法获得一切 你可以尝试 html html 如果您还想捕获 html 标签 您可以将它们连接到 html 如下所示 function getPageHTML return h
  • pandas 如何在时间序列数据上“get_dummies”

    如果我有一些时间序列数据 弥补一些 import numpy as np import pandas as pd np random seed 11 rows cols 50000 2 data np random rand rows co
  • 使用 segue 设置详细视图控制器

    背景 我有一个自定义 UIViewController 类 我在其中使用自定义注释填充 MKMapView 当用户选择注释时 会显示有关该注释的详细信息 并且还会显示一个按钮 供用户选择并调出另一个 UIViewController 其中包
  • 重播非循环 gif 图像

    我有一个非循环 gif 我将其用作两个 JLabel 的 ImageIcon 但不同时使用 我的问题是 当我将第二个 JLabel 的图标设置为 gif 时 动画已经播放过 因此它只显示最后一帧 您知道当 gif 设置为第二个 JLabel
  • VBA 中的哨兵对象

    我在网络上和我自己的项目中普遍看到具有以下模式的代码 Sub Func Application EnableEvents False some code Application EnableEvents True End Sub 自从有生以
  • 我自己的驱动程序是否需要 Windows 7 x64 中的数字签名

    我已经创建了驱动程序来在 Windows 7 x64 上挂接 ssdt 我怀疑是否需要对驱动程序进行数字签名才能在 x64 上以内核模式安装 否则我只需要 Windows 驱动套件即可安装它 除了 Windows Driver Kit WD
  • 获取维度长度,C# 数组

    int arr new int 2 5 var rows arr var cols arr Assert Equals 3 rows Assert Equals 6 cols 您可以使用GetLength some dimension st
  • 用于验证 IPv4 和 IPv6 地址(无主机名)的 JavaScript 正则表达式

    请建议一个可以验证的 JS 正则表达式 IPv4地址 IPv6地址 该正则表达式应该只验证地址而不验证主机名 我有完全相同的需要 所以我改编了正则表达式丹尼尔的精彩回答 这是我能找到的最准确的 不验证主机名 这里是 var expressi
  • Mongodb 带条件聚合查找

    我有一个名为article category其中存储所有article id属于以下类别category id像这样的数据格式 集合 1 article category article id 2015110920343902 all ca
  • Opencv cv::waitKey() 返回值

    我正在 Ubuntu 14 上调试一些使用 OpenCV 的 C 代码 已知该代码可以在 Ubuntu 12 上运行 也可能与其他 OpenCV 库构建一起运行 之前是什么 int key pressed waitKey 0 cout lt
  • getElementsByTagName() 相当于 textNodes

    有什么办法可以得到全部的集合吗textNode文档中的对象 getElementsByTagName 对于 Elements 来说效果很好 但是textNodes 不是元素 Update 我意识到这可以通过遍历 DOM 来完成 正如下面许多
  • 如何使用空手道功能文件中的 .js 文件中的参数调用 Javascript 函数

    可以说我在functions js 文件中创建了javascript 函数 function getReviews reviews var length reviews reviews length return length review
  • 从 Windows 7 中的 php 命令行脚本复制到剪贴板

    我有一个 php 5 5 脚本 我在 Windows 7 中从命令行运行该脚本 如下所示 C php 5 5 5 php exe C scripts putString php 我的问题是 是否可以将脚本中的内容复制到 Windows 剪贴
  • 使用 Guice Custom Scopes 和 Jersey 进行多租户

    我正在使用 Guice for DI 与 Jersey 开发多租户应用程序 我也使用 Dropwizard 但我认为这在这里并不重要 令我困扰的一件事是 某种tenancy id我的申请中到处都是 我的大多数网址如下所示 tenancy i
  • 合并两个具有复杂条件的 pandas 数据框

    我想合并两个数据框 让我们考虑以下两个 df df1 id A ts A course weight id1 2017 04 27 01 35 30 cotton 3 5 id1 2017 04 27 01 36 05 cotton 3 5
  • 如何在 Tomcat 的 web.xml 中映射欢迎文件的过滤器?

    我创建了一个Filter检查Cookies 与请求对象和forward相应的请求感谢this and this问题 现在我想映射这个Filter只是为了welcome file正如我在中声明的那样web xml 说我有welcome fil
  • 使用 Selenium 测试 AngularJS

    我在 ASP MVC AngularJS 堆栈上有一个 SPA 应用程序 我想测试 UI 现在我正在尝试 Selenium 与 PhantomJS 和 WebKit 驱动程序 这是一个示例测试页面 具有单个元素的视图 清单项目 li 从服务
  • http 文件访问和 php 会话

    如果站点有 php 会话来强制对站点上以 php 实现的页面进行身份验证 授权 那么相同的逻辑如何强制访问某些文件 假设目录中的文件存储库 因此 var www html 通过身份验证受到保护 但是 此 PHP 身份验证逻辑不会禁止用户简单
  • 关闭调试打印

    有时我有很多打印分散在函数周围来打印调试输出 为了切换这个调试输出 我想出了这个 def f debug False print builtins print if debug else lambda p None 或者 如果我需要打印除调
  • 为什么自动装箱会使 Java 中的某些调用变得不明确?

    今天我注意到自动装箱有时会导致方法重载解析中的歧义 最简单的例子似乎是这样的 public class Test static void f Object a boolean b static void f Object a Object