布尔值是否自动装箱到同一实例?

Do booleans auto-box to the same instance?

布尔值是否自动装箱到同一实例?

我有一个小测试表明他们可以,但我不打算在上面做任何赌注。有保障吗?

    @Test
    public void autoboxBooleans() {
        Multimap<Boolean, Integer> ids = HashMultimap.create();

        for (int i = 0; i < 10; i++) {
            Boolean rand = ThreadLocalRandom.current().nextBoolean();
            ids.put(rand, System.identityHashCode(rand));
        }

        System.out.println(ids); // {false=[453523494], true=[2024918163]}
    }

注意This question谈论0-127范围外的整数。

对于 Java111JLS 5.1.7 指出:

At run time, boxing conversion proceeds as follows:

  • If p is a value of type boolean, then boxing conversion converts p into a reference r of class and type Boolean, such that r.booleanValue() == p

[...]

If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.

JLS 没有明确说明 <wrapperType>::valueOf 方法用于自动装箱。实际上,Java 编译器通常会以这种方式实现它,但它是一个实现细节,可能(理论上)会发生变化。

所以......除了“常量表达式”的情况......你不应该依赖与Boolean.TRUEBoolean.FALSE对象引用相同的自动装箱布尔值 2.


1 - JLS 的早期版本对装箱做了更严格的声明。但这显然是对规范的故意更改。

2 - 您的应用程序可以采取步骤 手动 框布尔值使用 Boolean::valueOf (或其他方式)。但那是另一回事。并且可能不推荐,因为您必须确保始终如一地执行此操作。

注意:此答案对于 Java 7 和 8 是正确的,Java 9-11 在 JLS 中的措辞略有不同。


感谢 jtahlborn 的评论,我得以研究答案。

JLS 5.1.7 for Java 7&8 说(强调我的)

If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.

关于它的价值,Boolean#valueOf 的 javadoc 说

... If the specified boolean value is true, this method returns Boolean.TRUE; if it is false, this method returns Boolean.FALSE....