我如何从隐式的ClassTag[T]中获得类[T]?

时间:2022-05-06 20:44:00

I'd like to have a method like

我想要一个方法。

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

Inside this method I need to call a Java method (beyond my control) to create an instance of T that requires Class[T]:

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

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

How can I get Class[T] from ClassTag[T]? First I thought I could use runtimeClass from ClassTag, but it's type is Class[_], not Class[T]. Or is there any other implicit value that compiler can automatically provide, from which I can obtain Class[T]?

我怎样才能从ClassTag[T]获得类[T]?首先,我想我可以从ClassTag中使用runtimeClass,但它的类型是Class[_],而不是Class[T]。或者编译器可以自动提供其他隐式值,从中我可以获得类[T]?

1 个解决方案

#1


14  

Here is the ticket on getClass and the linked forum discussion in which Odersky speculates:

这里是关于getClass的门票和Odersky推测的链接论坛讨论:

You could also use a cast.

你也可以使用石膏。

Here is the duplicate ticket where getClass is fixed. 5.getClass also casts:

这是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]]

The limitation is reminiscent of this question about pattern matching with ClassTag, in which our naive expectations are also not met.

这种限制让人联想到与ClassTag模式匹配的问题,在这个问题中,我们的天真期望也没有得到满足。

Does the resistance to Class[A] represent the impedance mismatch between Scala types and the platform?

对类[A]的阻力是否代表了Scala类型与平台之间的阻抗不匹配?

Given the class type, all one can really do is newInstance. But reflective invocation with a constructor mirror won't give me my type back.

考虑到类类型,所有人都能做的就是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

That doesn't seem fair.

这似乎不公平。

As that mailing thread from 2008 concludes, you expect to use fewer casts in Scala.

从2008年开始,您希望在Scala中使用较少的类型转换。

BTW, it's not that I disbelieved the code comment, but:

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

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

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

[snip]

(剪)

 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        

#1


14  

Here is the ticket on getClass and the linked forum discussion in which Odersky speculates:

这里是关于getClass的门票和Odersky推测的链接论坛讨论:

You could also use a cast.

你也可以使用石膏。

Here is the duplicate ticket where getClass is fixed. 5.getClass also casts:

这是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]]

The limitation is reminiscent of this question about pattern matching with ClassTag, in which our naive expectations are also not met.

这种限制让人联想到与ClassTag模式匹配的问题,在这个问题中,我们的天真期望也没有得到满足。

Does the resistance to Class[A] represent the impedance mismatch between Scala types and the platform?

对类[A]的阻力是否代表了Scala类型与平台之间的阻抗不匹配?

Given the class type, all one can really do is newInstance. But reflective invocation with a constructor mirror won't give me my type back.

考虑到类类型,所有人都能做的就是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

That doesn't seem fair.

这似乎不公平。

As that mailing thread from 2008 concludes, you expect to use fewer casts in Scala.

从2008年开始,您希望在Scala中使用较少的类型转换。

BTW, it's not that I disbelieved the code comment, but:

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

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

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

[snip]

(剪)

 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