Given a type declaration, I am able to resolve the type argument.
scala> reflect.runtime.universe.typeOf[List[Int]] match {case x:TypeRef => x.args}
res10: List[reflect.runtime.universe.Type] = List(Int)
For a runtime value, The same method doesn't work.
scala> reflect.runtime.currentMirror.reflect(List(42)).symbol.toType match {case x:TypeRef => x.args}
res11: List[reflect.runtime.universe.Type] = List(B)
Is there a way to overcome the type erasure for reflected values?
An example based on TypeTag knowledge gained from reading Scala: What is a TypeTag and how do I use it? posted by Eugene Burmako in the comments on your question:
import scala.reflect.runtime.universe._
object ScalaApplication {
def main(args: Array[String]) {
printType(List(42))
printType(List("42"))
printType(List("42", 42))
}
def printType[T : TypeTag](t: T) {
println(typeOf[T])
}
}
This should give the output:
$ scala ScalaApplication.scala
List[Int]
List[String]
List[Any]
[UPDATE 1:]
However, if you want to be aware of the type assigned to a reference of type Any
you might have to opt for some sort of type aware wrapper:
import scala.reflect.runtime.universe._
object ScalaApplication {
def main(args: Array[String]) {
val anyWrapper = new AnyWrapper
List(1,2,3).foreach { i =>
i match {
case 1 => anyWrapper.any = 42
case 2 => anyWrapper.any = "a string"
case 3 => anyWrapper.any = true
}
print(anyWrapper.any)
print(" has type ")
println(anyWrapper.typeOfAny)
}
}
class AnyWrapper {
private var _any: Any = null
private var _typeOfAny: Type = null
def any = _any
def typeOfAny = _typeOfAny
def any_=[T: TypeTag](a: T) = {
_typeOfAny = typeOf[T]
_any = a
}
}
}
This should give the output:
$ scala ScalaApplication.scala
42 has type Int
a string has type String
true has type Boolean
But this solution still does not cover the case where the reference type is unknown at compile time.
[UPDATE 2:]
If the types are explicitly cast to reference of type Any
, you might have to enumerate all the possible types in a match statement in order to recover the type:
import scala.reflect.runtime.universe._
object ScalaApplication {
def main(args: Array[String]) {
List(1,2,3).foreach { i =>
val any: Any = i match {
case 1 => 42.asInstanceOf[Any]
case 2 => "a string".asInstanceOf[Any]
case 3 => true.asInstanceOf[Any]
}
print(any)
print(" has type ")
println(matchType(any))
}
}
def matchType(any: Any) = {
any match {
case a: Int => typeOf[Int]
case a: String => typeOf[String]
case a: Boolean => typeOf[Boolean]
}
}
}
This should give the output:
$ scala ScalaApplication.scala
42 has type Int
a string has type String
true has type Boolean
But this solution requires you to know (and list) all the possible types that you could receive in the any
value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With