注意这是一个社区帖子,应根据需要添加示例。如果您无法直接编辑答案以添加示例(问题示例或解决方案),请在评论中发布带有要点(或类似内容)的链接或添加单独的答案,以便稍后集成。
Scala 3可能根本不包含scala.reflect.runtime
(Dotty目前还没有,并且计划这样做并不确定)。虽然适用于Scala 2和Dotty的答案可能适用于过渡目的,并且可立即改进性能,但也欢迎使用Dotty特定的解决方案。
https://www.cakesolutions.net/teamblogs/ways-to-pattern-match-generic-types-in-scala
答案 0 :(得分:4)
TypeTag
在编译时生成(由于每个使用站点的宏扩展可能会产生大量的编译时间开销)并在运行时使用,也会产生一些潜在的运行时开销,具体取决于他们的用途。因此,即使在Scala 2中,它们也许应该只是最后的手段(我们希望在这里解决所有这些问题,因此不需要最后的手段)。相比之下,直接或间接使用instanceOf
的东西非常快。
instanceOf
是super fast。 classOf
(即Java的getClass
)几乎一样快。
ClassTag
上的参照平等也应该非常快。
如果可能,您可能需要考虑将类型包装在类中,以赋予其具体的“Java”类型。虽然通常会有开销,但您可以使用value classes。
包装类上的类型类通常是公开功能的好方法。顺便说一句,正如@Blaisorblade指出的那样,“类型标签只是一个无法无天的类型(使用方法typeName: String
和tpe: Type
)+实例实现”。这将我们带到下一个选项:
(目前Dotty不支持,但有计划)
虽然可能有点难以习惯,但最终结果应该是使用宏的代码比使用TypeTag
时更清晰。此外,宏的使用远远超过TypeTag
。
来自热门帖子Scala: What is a TypeTag and how do I use it?的TypeTag
的典型用例是对集合类型执行ad-hoc多态:
import scala.reflect.runtime.universe._
def meth[A : TypeTag](xs: List[A]) = typeOf[A] match {
case t if t =:= typeOf[String] => "list of strings"
case t if t <:< typeOf[Foo] => "list of foos"
}
scala> meth(List("string"))
res67: String = list of strings
scala> meth(List(new Bar))
res68: String = list of foos
与ClassTag
不同,TypeTag
是运行时反射。也许我在这里使用它错了,虽然这种行为非常令人惊讶。至少在REPL中,我没有收到以下任何警告:
def meth[A : ClassTag](xs: List[A]) = xs match {
case xs: List[String] => "list of strings"
case xs: List[Foo] => "list of foos"
}
meth(List(new Bar))
res10: String = "list of strings"
这是来自@smarter on gitter(假设我们不需要分别处理不同类型的空列表):
def meth[A](xs: List[A]) = xs match {
case Nil => "nil"
case (_: String) :: _ => "list of strings"
case (_: Foo) :: _ => 'list of foos"
}
这使用instanceOf
,所以它应该非常快。