在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?!
为什么会这样,我该如何解决呢?
我想添加一个答案,将问题概括为:如何在运行时获得我的列表类型的String表示
import scala.reflect.runtime.universe._
def whatListAmI[A : TypeTag](list : List[A]) = {
if (typeTag[A] == typeTag[java.lang.String]) // note that typeTag[String] does not match due to type alias being a different type
println("its a String")
else if (typeTag[A] == typeTag[Int])
println("its a Int")
s"A List of ${typeTag[A].tpe.toString}"
}
val listInt = List(1,2,3)
val listString = List("a", "b", "c")
println(whatListAmI(listInt))
println(whatListAmI(listString))
我想添加一个答案,将问题概括为:如何在运行时获得我的列表类型的String表示
import scala.reflect.runtime.universe._
def whatListAmI[A : TypeTag](list : List[A]) = {
if (typeTag[A] == typeTag[java.lang.String]) // note that typeTag[String] does not match due to type alias being a different type
println("its a String")
else if (typeTag[A] == typeTag[Int])
println("its a Int")
s"A List of ${typeTag[A].tpe.toString}"
}
val listInt = List(1,2,3)
val listString = List("a", "b", "c")
println(whatListAmI(listInt))
println(whatListAmI(listString))
我提出了一个相对简单的解决方案,在有限的使用情况下就足够了,本质上是在可以在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