为什么在Int的情况下Scala = =不同?

时间:2015-03-24 10:45:20

标签: scala scala-2.10

是不是应该在幕后调用equals?

scala> 1 equals 1l
res2: Boolean = false

scala> 1 == 1l
res3: Boolean = true

2 个答案:

答案 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。