12

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]:

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]?

Petr
  • 62,528
  • 13
  • 153
  • 317

1 Answers1

14

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

You could also use a cast.

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

/** 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.

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

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.

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.

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        
Community
  • 1
  • 1
som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • It's good research, but not a good answer. Links, quotes, source code, disassembly... So how do I get a `Class[T]` from a `ClassTag[T]`? (I mean I can figure it out, but I think the first priority of the answer should be to answer this question and only then provide context.) – Daniel Darabos Feb 17 '16 at 09:34
  • 1
    @DanielDarabos it says use a cast and then shows an example using a cast to go from ClassTag to Class. This answer goes way beyond the call of duty. The OP didn't have an opinion. – som-snytt Feb 17 '16 at 18:13
  • _"Use a cast"_ is a quote of a speculation from a forum. The "example" is a code snippet from the Scala runtime internals (`ScalaRunTime.scala`) and is just inserted without saying "this is how you do it". It returns a `jClass[T]`, which is a local alias for `Class[T]` in the file, but the readers of the answer don't know that. Anyway, I don't want to criticize the answer, I just wanted to give feedback. It's a very insightful answer regardless. – Daniel Darabos Feb 17 '16 at 18:30
  • @DanielDarabos thx for the feedback. Probably someone who can't read the example shouldn't be attempting to do this. I'm willing to aim low for some newbie questions. There's also the notion that a SO Q&A addresses the OP's problem at a certain time and is not always canonical or FAQ. Definition of green check is that it solved the OP's problem. Downvote means "not useful". – som-snytt Feb 17 '16 at 20:20