看看ClassTag#runtimeClass,它有一个返回类型Class[_],即Class根据我的理解,带有一个通配符参数.
我试图实现一个方法A => ClassTag[A]:
import scala.reflect._
scala> def f[A](x: A)(implicit ev: ClassTag[A]) = ev.runtimeClass
f: [A](x: A)(implicit ev: scala.reflect.ClassTag[A])Class[_]
Run Code Online (Sandbox Code Playgroud)
但是,def正如文档所示,该定义的输出是Class[_].
是否有可能改变f它的返回类型Class[A]?如果没有,那为什么不可能呢?
除非您更改签名,否则f您唯一的选择是将其Class[_]转换为Class[A].
在整个Scala标准库中只有一个方法返回一个Class[A],就是这样classOf.f[A]无法重写以使用,classOf[A]因为它是一种特殊的编译器方法,并且与可能不是类的泛型类型参数不兼容.你只会得到一个错误:
scala> def f[A: ClassTag](x: A) = classOf[A]
<console>:10: error: class type required but A found
def f[A: ClassTag](x: A) = classOf[A]
^
Run Code Online (Sandbox Code Playgroud)
没有强制转换你可以得到的最好的是x.getClass,但是这将返回一个Class[_ <: A](ClassTag不需要).
scala> def f[A](x: A): Class[_ <: A] = x.getClass
f: [A](x: A)Class[_ <: A]
scala> f(1)
res8: Class[_ <: Int] = class java.lang.Integer
scala> f(List(1, 2, 3))
res9: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon
Run Code Online (Sandbox Code Playgroud)
你可能会问,为什么_ <: A?
这个问题的答案也是你的定义f没有真正意义的原因.如果A是一个Int,那么能够返回一个Class[A]因为Int是一个类是有道理的.但如果A是List[Int]什么呢?List[Int]不是一个类,它是一种类型.这个班级是List,但是A != List,因此我们不能Class[A]一致地返回.但是,我们可以A在类型参数上有一个上限Class.