我知道什么类型的擦除。所以,我认为scala REPL无法准确检测到泛型类型
正如我上面提到的,scala无法在模式匹配中检测泛型类型,如下所示:
case list: List[Int]
但是当我声明List类型值时,scala会检测包含泛型类型的内容。
scala> val a = List(1,2,3)
a: List[Int] = List(1, 2, 3)
怎么可能?
答案 0 :(得分:3)
val a = List(1,2,3)
这相当于:
val a = List.apply[Int](1,2,3)
List.apply[Int](...)
的结果类型为List[Int]
,因此,类型推断器会将此类型分配给标识符a
。这发生在编译期间。 REPL不会在运行时“检测”该类型。
这与模式匹配不同:
val a: Any = ...
a match {
case list: List[Int] => ...
}
在这里,我们有一个值a
,我们没有任何类型信息。所以我们试图检查它是什么类型,但现在我们在运行时中执行此操作。在这里,我们确实无法确定确切的类型。我们在这里做的最好的事情就是匹配List[_]
。
汇总: 当您在REPL中键入一些代码时,它首先被编译为字节码然后进行评估。显示的类型信息来自编译阶段,因此不会遭受类型擦除。
答案 1 :(得分:1)
当你写:
val a = List(1,2,3)
Scala使用类型推断在编译期间查找最接近的匹配类型。基本上它会为你重写它:
val a: List[Int] = ...
它会在编译时使用此参数类型信息来键入检查代码并在之后将其删除,这样您就可以在程序中获得List[_]
。这是因为JVM以这种方式工作 - 类型擦除。
当您在运行时在列表上进行模式匹配时,它的类型信息将被删除,因此任何List
都匹配。 Scala编译器会在编译期间向您发出警告。
这在REPL和常规的compile->运行周期中的工作方式相同。