目前我有这个:
private def isCollectionLike[T](manifest: Manifest[T]):Boolean = { manifest.runtimeClass.toString.contains("scala.collection") }
我不喜欢这个解决方案,你能说一个更好的解决方案吗?
只是打电话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
不知道任何事情)关于斯卡拉).但它也更复杂,而且(目前)根本不是线程安全的,这是一个主要的限制.
另外,在您的情况下,您仍然需要处理数组作为特殊情况.