自动装箱是否调用 valueOf()?

2022-08-31 20:18:56

我试图确定以下陈述是否保证为真:

((Boolean)true) == Boolean.TRUE
((Boolean)true) == Boolean.valueOf(true)
((Integer)1) == Integer.valueOf(1)

我一直认为自动装箱等同于调用相应的类型。我看到的关于这个话题的每一次讨论似乎都支持我的假设。但我在JLS中能找到的只是以下内容(§5.1.7):valueOf()

如果装箱的值是介于 和(§3.10.1) 之间的整数文本,或者是布尔文本或 (§3.10.3),或者介于 和 包含之间的字符文本 (§3.10.4),则让 和 成为 的任意两个装箱转换的结果。总是这样。pint-128127truefalse'\u0000''\u007f'abpa == b

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

Oracle 的自动装箱教程实际上指出,编译为 ,其中 是 .但我不知道本教程是否应该被视为权威来源。li.add(i)li.add(Integer.valueOf(i))iint


*这是一个比 valueOf() 稍弱的保证,因为它仅指文字值。


答案 1

我首先质疑您的问题是编译器为自动装箱生成什么代码的欺骗?

但是,在您对@ElliottFrisch的评论之后,我意识到它是不同的:

我知道编译器就是这样做的。我试图弄清楚这种行为是否得到保证。

对于其他读者,假设“以这种方式行事”意味着使用 .valueOf

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

但是我看不出有任何理由不使用,特别是它使用缓存的值,并且是Joseph D. Darcy的这篇文章推荐的方式。valueOf


答案 2

在语言规范提到它之前,不能保证自动装箱等效于对静态方法的调用。这是一个实现方面,而不是拳击转换规范的一部分。从理论上讲,一个实现可以自由地使用另一种机制,只要它符合你在JLS中提到的规则。valueOf

在实践中,有许多 Sun JDK 错误报告(例如 JDK-4990346JDK-6628737)清楚地表明,当在 Java 5 中引入自动装箱时,其意图是让编译器依赖于 JDK-6628737 中所述:valueOf

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

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


推荐