Int与Integer的拆箱问题

一段程序从java迁移到scala后遇到的,

private val map = new java.util.concurrent.ConcurrentHashMap[String, Int]

val c = map.get(key)

// 下面的if语句在eclipse里提示
// comparing values of types Int and Null using `==' will always yield false
if (c == null) { 
    ...  
}

问题简化后如下:

scala> val m = new java.util.concurrent.ConcurrentHashMap[String, Int]
m: java.util.concurrent.ConcurrentHashMap[String,Int] = {}

scala> m.get("key")
res0: Int = 0

scala> val m = new java.util.concurrent.ConcurrentHashMap[String, java.lang.Integer]
m: java.util.concurrent.ConcurrentHashMap[String,Integer] = {}

scala> m.get("key")
res2: Integer = null

为何value设置为scala里的Int类型得到0而用java里的Integer确是null? 跟以前遇到的null造型为值类型时为何不抛异常 是相似的事

$ scala -Xprint:jvm -e 'val m = new java.util.concurrent.ConcurrentHashMap[String, Int]; val c = m.get("key")'
...
anon$1.this.m = new java.util.concurrent.ConcurrentHashMap();
anon$1.this.c = scala.Int.unbox(anon$1.this.m().get("key"));
...

$ scala -Xprint:jvm -e 'val n:Int = null.asInstanceOf[Int]' ...
anon$1.this.n = scala.Int.unbox(null);
...

scala> val n:Int = null.asInstanceOf[Int]
n: Int = 0

scala> scala.Int.unbox(null)
res3: Int = 0



scala> null.asInstanceOf[java.lang.Integer]
res5: Integer = null

scala> null.asInstanceOf[Int]
res6: Int = 0

scala.Int.unbox 注释里提到运行时是 scala.runtime.BoxesRunTime里的unboxToInt方法

package scala.runtime.BoxesRunTime;

public static int unboxToInt(Object i) {
    return i == null ? 0 : ((java.lang.Integer)i).intValue();
}

还是在对待Int类型时,两种语言设计上的差异,Scala里统一了primitive类型和引用类型。

Int与Integer的拆箱问题》上有3个想法

  1. 所以,如果是Java的集合类,就应该用java.lang.Long, java.lang.Integer
    如果是Scala的集合类,就应该用Scala的值类型

发表评论

电子邮件地址不会被公开。 必填项已用*标注