【问题标题】:How can I get Class[T] from an implicit ClassTag[T]?如何从隐式 ClassTag[T] 中获取 Class[T]?
【发布时间】:2013-08-04 08:19:32
【问题描述】:

我想要一个类似的方法

def retrieve[T](value: Option[T])(implicit ct: ClassTag[T]): T;

在这个方法中,我需要调用一个 Java 方法(超出我的控制范围)来创建一个需要 Class[T]T 实例:

public <T> T construct(clazz: Class<T> /* other arguments */) { ... }

如何从ClassTag[T] 获得Class[T]?首先我想我可以使用ClassTag 中的runtimeClass,但它的类型是Class[_],而不是Class[T]。还是编译器可以自动提供任何其他隐式值,我可以从中获取Class[T]

【问题讨论】:

  • 在使用 java 反射时不要害怕强制转换。只需asInstanceOf[Class[T]]

标签: class scala reflection scala-2.10


【解决方案1】:

Here is the ticket on getClass 和 Odersky 推测的 linked forum discussion

你也可以使用演员表。

Here is the duplicate ticket 其中getClass 是固定的。 5.getClass 也投:

/** Return the class object representing an unboxed value type,
 *  e.g. classOf[int], not classOf[java.lang.Integer].  The compiler
 *  rewrites expressions like 5.getClass to come here.
 */
def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] =
  classTag[T].runtimeClass.asInstanceOf[jClass[T]]

这个限制让人想起this question about pattern matchingClassTag,我们幼稚的期望也没有得到满足。

Class[A] 的阻抗是否代表 Scala 类型和平台之间的阻抗不匹配?

考虑到班级类型,真正能做的就是newInstance。但是使用构造函数镜像的反射调用不会给我我的类型。

scala> res24 reflectConstructor res25.asMethod
res27: reflect.runtime.universe.MethodMirror = constructor mirror for Bar.<init>(): Bar (bound to null)

scala> res27()
res28: Any = Bar@2eeb08d9

scala> bar.getClass.newInstance
res29: Bar = Bar@31512f0a

scala> classOf[Bar].newInstance
res30: Bar = Bar@2bc1d89f

这似乎不公平。

随着 2008 年的邮件主题结束,您希望在 Scala 中使用更少的强制转换。

顺便说一句,不是我不相信代码注释,而是:

scala> 5.getClass
res38: Class[Int] = int

scala> :javap -
  Size 1285 bytes
  MD5 checksum a30a28543087238b563fb1983d7d139b
  Compiled from "<console>"

[剪辑]

 9: getstatic     #27                 // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
12: iconst_5      
13: invokestatic  #33                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
16: getstatic     #38                 // Field scala/reflect/ClassTag$.MODULE$:Lscala/reflect/ClassTag$;
19: invokevirtual #42                 // Method scala/reflect/ClassTag$.Int:()Lscala/reflect/ClassTag;
22: invokevirtual #46                 // Method scala/runtime/ScalaRunTime$.anyValClass:(Ljava/lang/Object;Lscala/reflect/ClassTag;)Ljava/lang/Class;
25: putfield      #18                 // Field res38:Ljava/lang/Class;
28: return        

【讨论】:

  • 这是很好的研究,但不是一个好的答案。链接、引用、源代码、反汇编……那么我如何从ClassTag[T] 获得Class[T]? (我的意思是我可以弄清楚,但我认为答案的首要任务应该是回答这个问题,然后才提供上下文。)
  • @DanielDarabos 它说使用演员表,然后显示使用演员表从 ClassTag 到 Class 的示例。这个答案远远超出了职责范围。 OP没有意见。
  • “使用演员表” 是引用来自论坛的猜测。 “示例”是来自 Scala 运行时内部 (ScalaRunTime.scala) 的代码 sn-p,只是插入时没有说“这就是你的做法”。它返回一个jClass[T],它是文件中Class[T] 的本地别名,但答案的读者并不知道。无论如何,我不想批评答案,我只是想提供反馈。无论如何,这是一个非常有见地的答案。
  • @DanielDarabos 感谢您的反馈。可能无法阅读示例的人不应该尝试这样做。对于一些新手问题,我愿意把目标定得很低。还有一种观点是,SO Q&A 在特定时间解决了 OP 的问题,并不总是规范或常见问题解答。绿色检查的定义是它解决了OP的问题。 Downvote 的意思是“没用”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
相关资源
最近更新 更多