【问题标题】:Get containing generic types with ClassTag使用 ClassTag 获取包含泛型类型
【发布时间】:2015-03-04 11:03:57
【问题描述】:

我知道 guava 的 TypeToken 可以做到这一点:

class C[I, O]    

class A[T] {
  val tok = new TypeToken[T](getClass){}
}

val a = new A[C[Integer, String]]{}
println(a.tok)  // somepackage.C<java.lang.Integer, java.lang.String>

但是使用 scala 的 ClassTag,我得到:

class B[T: ClassTag] {
  // runtime class
  val clazz = implicitly[ClassTag[T]].runtimeClass
  // also tries to construct a guava type token
  val tok = TypeToken.of(clazz).asInstanceOf[TypeToken[T]]
}

val b = new B[C[Integer, String]]
println(b.clazz)  // class somepackage.C
println(b.tok)    // somepackage.C

因此,使用 ClassTag,C 包含的遗传类型会丢失。是否可以在 scala 中使用 ClassTag 或其他东西获取 somepackage.C?

谢谢!

【问题讨论】:

    标签: java scala reflection types guava


    【解决方案1】:

    我想你想要TypeTagtypeOf

    import scala.reflect.runtime.universe._
    
    class C[I, O]
    
    class A[T: TypeTag] {
      val tpe = typeOf[T]
    }
    
    val a = new A[C[Integer, String]]
    println(a.tpe) // C[java.lang.Integer,String]
    

    【讨论】:

    • 太棒了!谢谢你。
    【解决方案2】:

    TypeToken 做了一个有趣的把戏。假设你有这个:

    class A[T]
    class B extends A[String]
    

    虽然 Java 在运行时会擦除类型参数,但B 的超类不是A[T],而是A[String]。该信息被保留,并且可以被获取。所以当你这样做时:

    val tok = new TypeToken[T](getClass){}
    

    最后的{} 意味着您正在创建TypeToken匿名子类,它嵌套在A[T] 上,因此A[T] 的每个实例实际上都会导致一个不同的匿名子类。

    无论如何,这是基本思想,它依赖于嵌套在参数化类中的匿名子类。仅仅拥有ClassTag(主要是Class 的包装)还不够好。

    Scala 可以使用TypeTag 保存完整的类型信息,但这是有代价的。 Scala 的类型系统相当复杂,比 Java 复杂得多,因此,保留完整的类型信息需要大量代码。

    所以,虽然 ClassTag 主要依赖于 Java 捆绑的 Class,但附带 scala-library,要使用 TypeTag,您需要将 scala-reflect 添加到您的依赖项中,这在 Scala 2.11 上约为 4.2MB .4.

    然而,一旦你有了它,剩下的就变得微不足道了,如lmm所示(无耻地复制和粘贴来自他的answer):

    import scala.reflect.runtime.universe._
    
    class C[I, O]
    
    class A[T: TypeTag] {
      val tpe = typeOf[T]
    }
    
    val a = new A[C[Integer, String]]
    println(a.tpe) // C[java.lang.Integer,String]
    

    【讨论】:

    • 感谢您的解释。但是我们可以从 TypeTag 构造一个 java.lang.reflect.Type 吗?
    • @darkjh 我不这么认为。
    猜你喜欢
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多