Scala使用默认(泛型类型)参数命名参数

时间:2015-12-09 13:27:41

标签: java scala

在下面的scala代码中,NullPointerException将在第3个方法调用的入口处抛出。我检查了字节码。似乎在f(1, c=2)中,编译器在f$default$2的返回值上插入一个校验广播,将b的类型转换为Nothing。但在f(1)中,编译器不进行此类转换。为什么呢?

import scala.reflect.ClassTag
import scala.reflect._
object test {
    def f[T : ClassTag](a:T, b:T=null.asInstanceOf[T], c:Int=2)={ print("*"+classTag[T]+"*");println(a, b, c) }
    def main(args: Array[String]) {
        f(1)
        f(1, 2)
        f(1, c=3) //Null pointer!! But why f(1) is right? 
    }
}

2 个答案:

答案 0 :(得分:0)

很难推断编译器何时执行或不执行运行时检查,我将留给一些编译器专家,但.asinstanceOf很可能在类型参数应用Nothing时发送错误没有界限。

一般规则 - 试图在所有可能的情况下摆脱.asInstanceOf

对于您的方法,一个合法的定义可能是

def f[T >: Null : ClassTag](a: T, b: T = null, c: Int = 2) = { ... }

答案 1 :(得分:0)

null.asInstanceOf是一个坏主意,无论如何(永远不会抛出空值!)。 删除它,确实修复了NPE,但ClasTag变成 Nothing

看起来运行时试图在这种情况下使用第二个参数来提取ClassTag并且失败了。现在,为什么它在这种情况下这样做,但不是第一种情况f(1),我不知道。 有趣的是,f(1, null.asInstanceOf[Int], 3)也有效,所以问题必须与解决默认参数的方式有关。

您也可以f[Int](1, c=3)。这很有效。

更好的是,完全避免使用空值。这是scala。 null引用有点像java中的goto:你可以使用它,但真的,真的,真的不应该。