问题简化后看一下代码片段:
// Number引用类型
scala> def foo[T](t: T) = { t.asInstanceOf[Number] }
foo: [T](t: T)Number
scala> foo(null)
res3: Number = null
// Int值类型
scala> def foo[T](t: T) = { t.asInstanceOf[Int] }
foo: [T](t: T)Int
scala> foo(null)
res4: Int = 0
// 其它值类型
scala> class V(val i:Int) extends AnyVal
defined class V
scala> null.asInstanceOf[V]
res10: V = V@0
把 null 造型为java.lang.Number
这种引用类型的时候没有问题,但造型为scala里的值类型时,为何不抛出异常?与直觉不符。背后是装箱,拆箱所致。
在stackoverflow上也有讨论
// 不涉及到unboxing
scala> val a:Any = null.asInstanceOf[Int]
a: Any = null
// 涉及到unboxing
scala> val a = null.asInstanceOf[Int]
a: Int = 0
// 在scala.Int伴生对象里定义的运行时拆箱逻辑
def unbox(x: java.lang.Object): Int = x.asInstanceOf[java.lang.Integer].intValue()
另外,有人问为什么不抛出空指针异常,因为规范里是抛异常:
asInstanceOf[T ] returns the “null” object itself if T conforms to scala.AnyRef,and throws a NullPointerException otherwise.
A reference to any other member of the “null” object causes a NullPointerException to be thrown.
这个规范已经更新了,2.10里的规范已经没有要求抛出异常了。
https://issues.scala-lang.org/browse/SI-4437
https://github.com/scala/scala-dist/pull/104