是不是应该在幕后调用equals?
scala> 1 equals 1l
res2: Boolean = false
scala> 1 == 1l
res3: Boolean = true
答案 0 :(得分:4)
来自Programming in Scala 2nd Edition,第11章
1唯一的情况 == is不直接调用equals用于Java的盒装数字类,如Integer或Long。在Java中,新的Integer(1)没有 等于新的Long(1),即使对于原始值1 == 1L。以来 Scala是一种比Java更常规的语言,它是必要的 这种差异通过特殊套接这些类的==方法。 同样,##方法提供了散列的Scala版本 与Java的hashCode相同,除了盒装数字类型之外 与==一致。例如新的整数(1)和新的 Long(1)使用##进行哈希处理,即使它们的Java哈希代码是 不同。
答案 1 :(得分:2)
正如@MichaelLang所说,this回答可以帮助你,具体来说:
比较两个基元(盒装或未装箱)和==应该总是给出 通过将这些值比较为未装箱的结果 原语。当你直接调用equals时,你正在跳过这一切 软化逻辑,而是对待两个盒装的java理论 不同类型的价值总是不相等。
如果你分析字节码:
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等于1 然后
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。