为什么 Scala 的 == 在 Int 的情况下不同?
Why is Scala's == different in case of Int?
后台不是应该调用equals吗?
scala> 1 equals 1l
res2: Boolean = false
scala> 1 == 1l
res3: Boolean = true
来自 Programming in Scala 2nd Edition,第 11 章
1 The only cases where
== is does not directly call equals is for Java’s boxed numeric classes such as Integer or Long . In Java, a new Integer(1) does not
equal a new Long(1) even though for primitive values 1 == 1L . Since
Scala is a more regular language than Java it was necessary correct
this discrepancy by special-casing the == method for these classes.
Likewise, the ## method provides a Scala version of hashing that is
the same as Java’s hashCode , except for boxed numeric types, where it
works consistently with == . For in- stance new Integer(1) and new
Long(1) hash the same with ## even though their Java hashCode s are
different.
正如@MichaelLang 所建议的,this 答案可以帮助您,具体来说:
comparing two primitives (boxed or unboxed) with == should always give
the result you would have gotten by comparing those values as unboxed
primitives. When you call equals directly, you are skipping all that
softening logic and instead treated to java's theory that two boxed
values of different types are always unequal.
如果分析字节码:
1 == 1l 产生
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L;
8: aload_0
9: iconst_1
10: putfield #17 // Field res0:Z
13: return
直接比较两个原始 1 的值,但是如果您检查:
1 等于 1l 然后
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L;
8: aload_0
9: iconst_1
10: invokestatic #27 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
13: lconst_1
14: invokestatic #31 // Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
17: invokevirtual #35 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
20: putfield #17 // Field res0:Z
23: return
您可以看到将 1l 基元装箱到 Long 对象中,然后执行等式。
后台不是应该调用equals吗?
scala> 1 equals 1l
res2: Boolean = false
scala> 1 == 1l
res3: Boolean = true
来自 Programming in Scala 2nd Edition,第 11 章
1 The only cases where == is does not directly call equals is for Java’s boxed numeric classes such as Integer or Long . In Java, a new Integer(1) does not equal a new Long(1) even though for primitive values 1 == 1L . Since Scala is a more regular language than Java it was necessary correct this discrepancy by special-casing the == method for these classes. Likewise, the ## method provides a Scala version of hashing that is the same as Java’s hashCode , except for boxed numeric types, where it works consistently with == . For in- stance new Integer(1) and new Long(1) hash the same with ## even though their Java hashCode s are different.
正如@MichaelLang 所建议的,this 答案可以帮助您,具体来说:
comparing two primitives (boxed or unboxed) with == should always give the result you would have gotten by comparing those values as unboxed primitives. When you call equals directly, you are skipping all that softening logic and instead treated to java's theory that two boxed values of different types are always unequal.
如果分析字节码:
1 == 1l 产生
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L;
8: aload_0
9: iconst_1
10: putfield #17 // Field res0:Z
13: return
直接比较两个原始 1 的值,但是如果您检查:
1 等于 1l 然后
0: aload_0
1: invokespecial #19 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #21 // Field MODULE$:L;
8: aload_0
9: iconst_1
10: invokestatic #27 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
13: lconst_1
14: invokestatic #31 // Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
17: invokevirtual #35 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
20: putfield #17 // Field res0:Z
23: return
您可以看到将 1l 基元装箱到 Long 对象中,然后执行等式。