我有以下功能来检查它是List[Int]
还是List[String]
。但如果我检查如下,总是如此。为什么以及如何定义检查List[Int]
或List[String]
类型的函数。
if(checkIntCollection(List("q","aa","aa"))){
Logger.info("it is true")
} else {
Logger.info("it is false")
}
OR
if(checkIntCollection(List(1,2,3))){
Logger.info("it is true")
} else {
Logger.info("it is false")
}
以下是检查: -
def checkIntCollection[T](v: T) : Boolean = v match {
case _: List[Int] =>
Logger.info("It is List[Int] found")
true
case _ =>
Logger.info("It is unknown")
false
}
def checkStringCollection[T](v: T) : Boolean = v match {
case _: List[String] =>
Logger.info("It is List[String] found")
true
case _ =>
Logger.info("It is unknown")
false
}
答案 0 :(得分:6)
正如其他答案中所述,类型擦除会使您的匹配表达式检查List
而不是List[Int]
,因此结果并非人们所期望的那样。
但是,您可以使用TypeTag
来规避多态类型的类型擦除。请注意,TypeTag
s 可能使用Reflection
,这可能会对性能产生负面影响。
import scala.reflect.ClassTag
import scala.reflect.runtime.universe._
object RichClass {
def unapply[T](a: RichClass[T]): Option[T] = Option(a.value)
}
implicit class RichClass[T](val value: T)(implicit val classTag: ClassTag[T], val typeTag: TypeTag[T]) {}
def isType[T : ClassTag : TypeTag](richClass: RichClass[_]): Boolean = {
richClass match {
case RichClass(elem: T) if richClass.typeTag.tpe =:= typeOf[T] => true
case _ => false
}
}
然后你可以像这样使用它
val stringList = List("A", "B")
val intList = List(1, 2, 3)
assert(isType[List[String]](stringList))
assert(!isType[List[String]](intList))
assert(isType[List[Int]](intList))
assert(!isType[List[Int]](stringList))
答案 1 :(得分:5)
由于类型擦除,这种情况正在发生。如果使用警告编译,您会注意到它表示您的类型测试没用,因为包含的类型在运行时不可见。
在运行时,T
的类型为List
,而不是List[String]
或List[Int]
事实上,你正试图在所有方面做到一个大代码的味道 - 你怎么不知道你有什么?