Generics Scala-从泛型类型获取类对象

Generics Scala-从泛型类型获取类对象,generics,scala,manifest,Generics,Scala,Manifest,是否可以纯粹从泛型参数创建类对象?例如: class myclass[T] { def something(): Class[_ <: T] = classOf[T] //this doesn't work } classmyclass[T]{ def something():Class[\up>.erasure为您提供类型擦除到的类型。如果您需要完整的类型信息,则应返回清单 scala> class MyClass[A] { | def stuff(

是否可以纯粹从泛型参数创建类对象?例如:

class myclass[T] { 
  def something(): Class[_ <: T] = 
    classOf[T] //this doesn't work
}
classmyclass[T]{

def something():Class[\up>
.erasure
为您提供类型擦除到的类型。如果您需要完整的类型信息,则应返回
清单

scala> class MyClass[A] {
     |   def stuff(implicit m: Manifest[A]): Class[_] = m.erasure
     | }
defined class MyClass

scala> new MyClass[Int].stuff
res551: java.lang.Class[_] = int

scala> new MyClass[List[Int]].stuff
res552: java.lang.Class[_] = class scala.collection.immutable.List

scala> class MyClass[A] {
     |   def stuff(implicit m: Manifest[A]): Manifest[A] = m
     | }
defined class MyClass

scala> new MyClass[Int].stuff
res553: Manifest[Int] = Int

scala> new MyClass[List[Int]].stuff
res554: Manifest[List[Int]] = scala.collection.immutable.List[Int]

您可以将
m.erasure
的结果强制转换为
类[T]

class myclass[T] { 
    def something()(implicit m: Manifest[T]): Class[T] = 
        m.erasure.asInstanceOf[Class[T]]
}
这适用于基本(非泛型)类型:

但是请注意,如果我为
T
使用像
List[String]
这样的实例化类型构造函数,会发生什么:

scala> new myclass[List[String]]().something()
res6: Class[List[String]] = class scala.collection.immutable.List
由于擦除,对于给定类型构造函数的所有可能实例化,只有一个
对象

编辑 我不知道为什么
Manifest[T]。擦除
返回
Class[\u]
而不是
Class[T]
,但如果我不得不推测,我会说这是为了阻止您使用
上的方法,这些方法允许您比较两个类的相等性或子类型关系,因为当
被实例化泛型类型参数化时,这些方法会给出错误的答案

比如说,

scala> classOf[List[String]] == classOf[List[Int]]
res25: Boolean = true

scala> classOf[List[String]].isAssignableFrom(classOf[List[Int]])
res26: Boolean = true
这些结果可能会让您大吃一惊和/或导致程序中出现错误。您通常不应该以这种方式比较类,而应该传递
Manifest
s来比较它们,因为它们有更多信息*:

scala> manifest[List[String]] == manifest[List[Int]]
res27: Boolean = false

scala> manifest[List[String]] >:> manifest[List[Int]]
res28: Boolean = false
据我所知,
Manifest
s在大多数用例中都意味着取代
es……但当然,如果您使用的框架需要
,那么没有太多选择。我想强制执行
擦除
的结果只是一种“责任确认”您使用劣质产品的风险由您自己承担:)


*请注意,正如上面所说,这些清单比较运算符“应仅被视为近似值,因为清单中还没有充分表示类型一致性的许多方面。”

因此,如果我需要一个实际的
类[\uu]调用,该怎么办?scala为什么不只是生成
类[t]
擦除的返回类型
?在编译过程中似乎可以保证这一点。@dhg我认为擦除并没有给你一个参数化的
,因为根据定义它是“一个代表将被擦除的U类型的类”。类的擦除不包含其参数。但我不确定为什么没有其他方法返回参数化类。这可能是来自Java的
class
类的一些限制。例如,
List(1,2,3)。getClass
返回一个
class[\uu]
@pelotom感谢您的大力响应。您的分析实际上非常有趣,而且非常有意义。与其他scala用户一样,我避免使用强制转换,因为这通常意味着您做错了什么。正如您所指出的,如果不是与外部框架(如d“责任确认”似乎很恰当。这个答案是为Scala 2.10和更高版本准备的,因为清单已被弃用。它在Scala 2.12中返回一个
Class[\u]
,而“runtimeClass”上的文档说“注意,
T
和[the”]之间没有子类型关系。”你知道如何实际获得
Class[T]
?@Rich,您可以使用
.asinstanteof[Class[T]
来转换
类[\u]
运行时类,这似乎是可行的,谢谢。文档建议,在某些情况下,这将不起作用,尽管……“T和[That]之间没有子类型关系”。我现在想不出一个例子。
scala> classOf[List[String]] == classOf[List[Int]]
res25: Boolean = true

scala> classOf[List[String]].isAssignableFrom(classOf[List[Int]])
res26: Boolean = true
scala> manifest[List[String]] == manifest[List[Int]]
res27: Boolean = false

scala> manifest[List[String]] >:> manifest[List[Int]]
res28: Boolean = false
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass