Java 中是否保证 new Integer(i) == i ?

发布于 2024-09-01 03:34:28 字数 704 浏览 9 评论 0原文

考虑以下代码片段:

    int i = 99999999;
    byte b = 99;
    short s = 9999;
    Integer ii = Integer.valueOf(9); // should be within cache

    System.out.println(new Integer(i) == i); // "true"
    System.out.println(new Integer(b) == b); // "true"
    System.out.println(new Integer(s) == s); // "true"
    System.out.println(new Integer(ii) == ii); // "false"

很明显为什么最后一行将 ALWAYS 打印 "false":我们使用 == 引用身份比较,并且对象将永远==到已经存在的对象。

问题是关于前 3 行:这些比较是否保证在原始 int 上,与 Integer 自动拆箱?是否存在原语被自动装箱并执行参考身份比较的情况? (这一切都将是false!)

Consider the following snippet:

    int i = 99999999;
    byte b = 99;
    short s = 9999;
    Integer ii = Integer.valueOf(9); // should be within cache

    System.out.println(new Integer(i) == i); // "true"
    System.out.println(new Integer(b) == b); // "true"
    System.out.println(new Integer(s) == s); // "true"
    System.out.println(new Integer(ii) == ii); // "false"

It's obvious why the last line will ALWAYS prints "false": we're using == reference identity comparison, and a new object will NEVER be == to an already existing object.

The question is about the first 3 lines: are those comparisons guaranteed to be on the primitive int, with the Integer auto-unboxed? Are there cases where the primitive would be auto-boxed instead, and reference identity comparisons are performed? (which would all then be false!)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌酱 2024-09-08 03:34:28

是的。 JLS §5.6.2 指定二进制数字提升的规则。部分:

当运算符应用二进制时
数字提升为一对
操作数,每个操作数必须表示一个
可转换为数字的值
类型,以下规则适用,在
顺序,使用加宽转换
(§5.1.2) 将操作数转换为
必要:

如果任何操作数是
引用类型、拆箱转换
执行(§5.1.8)。

二进制数字提升适用于多个数字运算符,包括“数字相等运算符 == 和 !=”。

JLS §15.21.1(数字相等运算符 == 和 !=) 指定:

如果操作数相等
运算符都是数字类型,或者
一个是数字类型,另一个是数字类型
可转换(§5.1.8)为数字
类型,二进制数字提升是
对操作数执行(第 5.6.2 节)。

相比之下,JLS §15.21.3(参考相等运算符 == 和 !=)提供:

如果操作数相等
运算符都是任一引用
类型或 null 类型,然后
操作是对象相等

这符合装箱和拆箱的一般理解,只有在不匹配时才会执行。

Yes. JLS §5.6.2 specifies the rules for binary numeric promotion. In part:

When an operator applies binary
numeric promotion to a pair of
operands, each of which must denote a
value that is convertible to a numeric
type, the following rules apply, in
order, using widening conversion
(§5.1.2) to convert operands as
necessary:

If any of the operands is of a
reference type, unboxing conversion
(§5.1.8) is performed.

Binary numeric promotion applies for several numeric operators, including "the numerical equality operators == and !=."

JLS §15.21.1 (Numerical Equality Operators == and !=) specifies:

If the operands of an equality
operator are both of numeric type, or
one is of numeric type and the other
is convertible (§5.1.8) to numeric
type, binary numeric promotion is
performed on the operands (§5.6.2).

In contrast, JLS §15.21.3 (Reference Equality Operators == and !=) provides:

If the operands of an equality
operator are both of either reference
type or the null type, then the
operation is object equality

This fits the common understanding of boxing and unboxing, that's it only done when there's a mismatch.

陌若浮生 2024-09-08 03:34:28

我将首先准确地解释何时 == 是引用相等,以及准确地何时 它是数值相等。引用相等的条件比较简单,所以先解释一下。

JLS 15.21.3 引用相等运算符 = =!=

如果相等运算符的操作数均为引用类型或null类型,则该操作为对象相等。

这解释了以下内容:

System.out.println(new Integer(0) == new Integer(0)); // "false"

两个操作数都是Integer,它们是引用类型,这就是为什么==是引用相等比较,并且两个new对象之间永远不会==,所以这就是它打印false的原因。

要使 == 数值相等,至少有一个操作数必须是数值类型;指定如下:

JLS 15.21.1 数值相等运算符 ==!=

如果相等运算符的操作数两者都是数字类型,或者一个是数字类型并且另一个可以转换为数字类型,对操作数执行二进制数字提升。如果操作数的提升类型为intlong,则执行整数相等测试;如果提升的类型是 float 或double`,则执行浮点相等测试。

请注意,二进制数字提升执行值集转换和拆箱转换。

因此,请考虑以下情况:

System.out.println(new Integer(0) == 0); // "true"

这将打印 true,因为:

  • 右操作数 数字 int 类型
  • 左操作数可转换为 一个数字类型,通过拆箱为 int
  • 因此 == 是一个数字相等运算

摘要

  • 如果 ==== 的两个操作数code>!= 是引用类型,它始终是引用相等操作
    • 操作数是否可以转换为数字类型并不重要
  • 如果至少有一个操作数是数值类型,则它将始终是数值相等运算
    • 如有必要,将对一个(最多!)个操作数执行自动拆箱

参考文献

相关问题

I will first explain precisely when == is a reference equality, and precisely when it's a numerical equality. The conditions for reference equality is simpler, so it will be explained first.

JLS 15.21.3 Reference Equality Operators == and !=

If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.

This explains the following:

System.out.println(new Integer(0) == new Integer(0)); // "false"

Both operands are Integer, which are reference types, and that's why the == is reference equality comparison, and two new objects will never be == to each other, so that's why it prints false.

For == to be numerical equality, at least one of the operand must be a numeric type; this is specified as follows:

JLS 15.21.1 Numerical Equality Operators == and !=

If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible to numeric type, binary numeric promotion is performed on the operands. If the promoted type of the operands is int or long, then an integer equality test is performed; if the promoted type is float ordouble`, then a floating-point equality test is performed.

Note that binary numeric promotion performs value set conversion and unboxing conversion.

Thus, consider the following:

System.out.println(new Integer(0) == 0); // "true"

This prints true, because:

  • the right operand is a numeric int type
  • the left operand is convertible to a numeric type, by unboxing to int
  • therefore == is a numerical equality operation

Summary

  • If both operands of == and != are reference types, it will always be a reference equality operation
    • It doesn't matter if the operands are convertible to numeric types
  • If at least one of the operand is a numeric type, it will always be a numerical equality operation
    • Auto-unboxing on one (at most!) of the operands will be performed if necessary

References

Related questions

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文