在Scala中,如果你实例化一个List[Int],你可以验证你的实例是一个List,你可以验证它的任何单个元素是否是Int,但不能验证它是否是List[Int],这很容易验证:

scala> List(1,2,3) match {
     | case l : List[String] => println("A list of strings?!")
     | case _ => println("Ok")
     | }
warning: there were unchecked warnings; re-run with -unchecked for details
A list of strings?!

unchecked选项直接将责任归咎于类型擦除:

scala>  List(1,2,3) match {
     |  case l : List[String] => println("A list of strings?!")
     |  case _ => println("Ok")
     |  }
<console>:6: warning: non variable type-argument String in type pattern is unchecked since it is eliminated by erasure
        case l : List[String] => println("A list of strings?!")
                 ^
A list of strings?!

为什么会这样,我该如何解决呢?


当前回答

由于Java不知道实际的元素类型,我发现使用List[_]最有用。然后警告消失了,代码描述了现实——它是一个未知事物的列表。

其他回答

我想知道这是否是一个合适的变通方案:

scala> List(1,2,3) match {
     |    case List(_: String, _*) => println("A list of strings?!")
     |    case _ => println("Ok")
     | }

它不匹配“空列表”的情况,但它给出了一个编译错误,而不是警告!

error: type mismatch;
found:     String
requirerd: Int

另一方面,这似乎工作....

scala> List(1,2,3) match {
     |    case List(_: Int, _*) => println("A list of ints")
     |    case _ => println("Ok")
     | }

这样不是更好吗,还是我没抓住重点?

由于Java不知道实际的元素类型,我发现使用List[_]最有用。然后警告消失了,代码描述了现实——它是一个未知事物的列表。

我提出了一个相对简单的解决方案,在有限的使用情况下就足够了,本质上是在可以在match语句中使用的包装器类中包装会遭受类型擦除问题的参数化类型。

case class StringListHolder(list:List[String])

StringListHolder(List("str1","str2")) match {
    case holder: StringListHolder => holder.list foreach println
}

这具有预期的输出,并将case类的内容限制为所需的类型String Lists。

更多详情请访问:http://www.scalafied.com/?p=60

在Scala中有一种方法可以克服类型擦除问题。在克服匹配1中的类型擦除和克服匹配2中的类型擦除(方差)中,解释了如何编写一些帮助程序来包装类型,包括方差,以进行匹配。

使用模式匹配保护

    list match  {
        case x:List if x.isInstanceOf(List[String]) => do sth
        case x:List if x.isInstanceOf(List[Int]) => do sth else
     }