确定Manofst [T]的T是否是一个集合

时间:2013-12-16 08:23:25

标签: scala reflection manifest

目前我有这个:

private def isCollectionLike[T](manifest: Manifest[T]):Boolean = {
   manifest.runtimeClass.toString.contains("scala.collection")
}

我不喜欢这个解决方案,你能说一个更好的解决方案吗?

1 个答案:

答案 0 :(得分:9)

只需致电Class#isAssignable即可:

def isCollectionLike[T](manifest: Manifest[T]):Boolean = {
  classOf[scala.collection.TraversableLike[_,_]].isAssignableFrom(manifest.runtimeClass)
}

强制性REPL测试:

scala> isCollectionLike(manifest[List[Int]])
res17: Boolean = true

scala> isCollectionLike(manifest[String])
res18: Boolean = false

scala> isCollectionLike(manifest[scala.collection.SeqLike[Int,_]])
res19: Boolean = true

请注意,这不适用于数组,原因很简单,scala数组现在(因为scala 2.8)直接映射到udnerlying JVM数组, 并且因此不继承TraversableLike(如果感兴趣,可以查看http://docs.scala-lang.org/sips/completed/scala-2-8-arrays.html)。

scala> isCollectionLike(manifest[Array[String]])
res20: Boolean = false

因此,您必须将其作为特殊情况处理,或者找到更好的方法来测试集合。

作为旁注,这些天有一种替代java反射scala自己的反射api(另外Manifest被弃用而不是TypeTag), 它具有理解所有scala特定功能的巨大优势 (由Class重新启动的runtimeClass实例对scala一无所知。 但它也更复杂,并且(目前)根本不是线程安全的,这是一个主要的限制。

另外,在你的情况下,你仍然需要处理数组作为特殊情况。