null造型为值类型时为何不抛异常

问题简化后看一下代码片段:

// 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

null造型为值类型时为何不抛异常》上有2个想法

  1. 在java里null造型为int类型的时候是一定抛出异常的

    ➜ cat A.java
    public class A {
    public static void main(String[] args) {
    //int i = (Integer)null;
    Integer i = (Integer)null;
    int i2 = (int)i;
    System.out.println(i2 > 0);
    }
    }

    ➜ java A
    Exception in thread “main” java.lang.NullPointerException
    at A.main(A.java:5)

发表评论

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