查看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[_]
但是,正如文档所示,def
定义的输出是Class[_]
。
是否可以更改f
以使其返回类型为Class[A]
?如果没有,那为什么不可能?
答案 0 :(得分:5)
除非您更改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]
^
您可以使用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
你可能会问,为什么_ <: A
?
这个问题的答案也是你f
的定义没有意义的原因。如果A
是Int
,则能够返回Class[A]
是有意义的,因为Int
是一个类。但是如果A
是List[Int]
怎么办? List[Int]
不是一个类,它是一个类型。该课程为List
,但A != List
,因此我们无法始终如一地返回Class[A]
。但是,我们可以在A
的类型参数上有Class
的上限。