autoboxing是否调用valueOf()?

shm*_*sel 50 java autoboxing boxing

我正在尝试确定以下语句是否保证是真的:

((Boolean)true) == Boolean.TRUE
((Boolean)true) == Boolean.valueOf(true)
((Integer)1) == Integer.valueOf(1)
Run Code Online (Sandbox Code Playgroud)

我一直认为自动装箱相当于调用valueOf()相应的类型.我在这个主题上看到的每一个讨论似乎都支持我的假设.但我在JLS中找到的只有以下内容(§5.1.7):

如果该值p被装箱是整数文本类型的int之间-128127包容性(§3.10.1)或布尔值truefalse(§3.10.3),或字符之间文字'\u0000''\u007f'包容性(§3.10.4),然后让ab是任何两个拳击转换的结果p.情况总是如此a == b.

这描述的行为*相似valueOf().但似乎没有任何valueOf()实际调用的保证,这意味着理论上可以有一个实现为自动装箱值保留一个单独的专用缓存.在这种情况下,缓存的自动装箱值与常规缓存的装箱值之间可能不存在标识相同性.

Oracle的自动装箱教程说明了li.add(i)编译到的事实li.add(Integer.valueOf(i)),其中i是一个int.但我不知道该教程是否应被视为权威来源.


*这是一个稍微弱一点的保证valueOf(),因为它只是指字面值.

Jea*_*ard 29

我首先提出你的问题是编译器为自动装箱生成了什么代码?

但是,在您对@ElliottFrisch发表评论后,我发现它有所不同:

我知道编译器的行为方式.我想弄清楚这种行为是否得到保证.

对于其他读者,假设"行为方式"意味着使用valueOf.

请记住,Java有多个编译器.为了"合法",他们必须遵守JLS中给出的合同.因此,只要遵守此处的所有规则,就无法保证内部如何实现自动装箱.

但我认为没有任何理由不使用valueOf,特别是它使用缓存的值,并且是Joseph D. Darcy在本文中推荐的方式.

  • @shmosel JLS 意味着当你有一个带有 `static Integer foo() { return 42; 的类 `A` 时 }` 和一个带有 `static Integer bar() { return 42; 的类 `B` }`,然后是 `A.foo() == B.bar()` 并且它没有说“仅当使用相同的编译器时”。因此,当一个类使用“Integer.valueOf(int)”使用“javac”进行编译时,另一个类必须以“Integer”结束,该“Integer”也由“Integer.valueOf(int)”返回,无论使用的是哪个编译器。用于“B”。它可以插入额外的缓存机制,但对象的来源必须相同,以确保保证引用相等。 (2认同)

man*_*uti 18

在语言规范提到之前,不能保证自动装箱等同于对静态valueOf方法的调用.它是一个实现方面,不是装箱转换规范的一部分.理论上,只要符合您在JLS中提到的规则,实现就可以自由使用其他机制.

在实践中,有许多Sun JDK错误报告(例如JDK-4990346JDK-6628737)明确暗示当在Java 5中引入自动装箱时,目的是让编译器依赖valueOfJDK-6628737中所述:

JDK 5中为javac引入了静态工厂方法Integer.valueOf(int),Long.valueOf(long)等,以实现自动装箱规范所需的缓存行为.

但这只适用于javac,不一定是所有编译器.