4

This seems like a simple question, but it's very challenging to search for, so I'm asking a new question. My apologies if it's already been asked.

Due to the compiler bug described here Scala 2.11.5 compiler crash with type aliases and manifests (also here https://issues.scala-lang.org/browse/SI-9155), I need to use scala TypeTags and friends for discovery of type parameters to methods. However, I then need to use that type information in a Java library that uses java.lang.Class and java.lang.reflect.Type.

How can I convert a scala.reflect.runtime.universe Type into a java.lang.reflect.Type or java.lang.Class?

Put concretely, how would I fill out the body of this method:

def typeFor[T](implicit tag: TypeTag[T]): java.lang.reflect.Type = ...

or, if that's not possible:

def typeFor[T](implicit tag: TypeTag[T]): java.lang.Class[T] = ...

And note, due to the bug posted above, I cannot use scala.reflect.Manifest.

Community
  • 1
  • 1
Yona Appletree
  • 8,801
  • 6
  • 35
  • 52
  • If you're willing to require a `ClassTag` rather than a `TypeTag` you can then just call `.runtimeClass` on it. – lmm Feb 18 '15 at 10:20
  • Looks like this is a duplicate of http://stackoverflow.com/questions/12901823/any-way-to-obtain-a-java-class-from-a-scala-2-10-type-tag-or-symbol – Yona Appletree Feb 19 '15 at 18:44

3 Answers3

2

The short answer is no, but you can try to do something similar to this SO question. However there is an open ticket....

Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
1

This may have some limitations I'm not aware of, but you could drop down to Java reflection and try something like:

import scala.util.control.Exception._

def typeMe[T](implicit t: TypeTag[T]) = {
  catching(classOf[Exception]) opt Class.forName(t.tpe.typeSymbol.asClass.fullName)
}

println(typeMe[String])
println(typeMe[ClassTag[_]])

Results in:

Some(class java.lang.String)
Some(interface scala.reflect.ClassTag)
Rich Henry
  • 1,837
  • 15
  • 25
  • After playing with it for a bit, I came up with this: def typeFor(tpe: ScalaType) = runtimeMirror(getClass.getClassLoader).runtimeClass(tpe). Which seems to work, but I'm not sure if there's some hidden problems with it. – Yona Appletree Feb 18 '15 at 20:23
  • Cool. I thought you had needed a Java object, that method looks like it returns a RuntimeClass object. Glad you're making progress. – Rich Henry Feb 18 '15 at 22:51
  • In the context of a runtimeMirror, it is a Class object. But you do have to perform an unsafe cast. – Yona Appletree Feb 19 '15 at 18:01
0

The way I solved it with manifests, was:

  private def typeFromManifest(m: Manifest[_]): Type = {
if (m.typeArguments.isEmpty) { m.runtimeClass }
else new ParameterizedType {
  def getRawType = m.runtimeClass
  def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray
  def getOwnerType = null
}

}

Right now I'm trying to solve this using something other than Manifest which should be removed from scala runtime.

Noam
  • 1,022
  • 8
  • 8