I want to get the type of a variable at runtime

Solution 1:

So, strictly speaking, the "type of a variable" is always present, and can be passed around as a type parameter. For example:

val x = 5
def f[T](v: T) = v
f(x) // T is Int, the type of x

But depending on what you want to do, that won't help you. For instance, may want not to know what is the type of the variable, but to know if the type of the value is some specific type, such as this:

val x: Any = 5
def f[T](v: T) = v match {
  case _: Int    => "Int"
  case _: String => "String"
  case _         => "Unknown"
}
f(x)

Here it doesn't matter what is the type of the variable, Any. What matters, what is checked is the type of 5, the value. In fact, T is useless -- you might as well have written it def f(v: Any) instead. Also, this uses either ClassTag or a value's Class, which are explained below, and cannot check the type parameters of a type: you can check whether something is a List[_] (List of something), but not whether it is, for example, a List[Int] or List[String].

Another possibility is that you want to reify the type of the variable. That is, you want to convert the type into a value, so you can store it, pass it around, etc. This involves reflection, and you'll be using either ClassTag or a TypeTag. For example:

val x: Any = 5
import scala.reflect.ClassTag
def f[T](v: T)(implicit ev: ClassTag[T]) = ev.toString
f(x) // returns the string "Any"

A ClassTag will also let you use type parameters you received on match. This won't work:

def f[A, B](a: A, b: B) = a match {
  case _: B => "A is a B"
  case _ => "A is not a B"
}

But this will:

val x = 'c'
val y = 5
val z: Any = 5
import scala.reflect.ClassTag
def f[A, B: ClassTag](a: A, b: B) = a match {
  case _: B => "A is a B"
  case _ => "A is not a B"
}
f(x, y) // A (Char) is not a B (Int)
f(x, z) // A (Char) is a B (Any)

Here I'm using the context bounds syntax, B : ClassTag, which works just like the implicit parameter in the previous ClassTag example, but uses an anonymous variable.

One can also get a ClassTag from a value's Class, like this:

val x: Any = 5
val y = 5
import scala.reflect.ClassTag
def f(a: Any, b: Any) = {
  val B = ClassTag(b.getClass)
  ClassTag(a.getClass) match {
    case B => "a is the same class as b"
    case _ => "a is not the same class as b"
  }
}
f(x, y) == f(y, x) // true, a is the same class as b

A ClassTag is limited in that it only covers the base class, but not its type parameters. That is, the ClassTag for List[Int] and List[String] is the same, List. If you need type parameters, then you must use a TypeTag instead. A TypeTag however, cannot be obtained from a value, nor can it be used on a pattern match, due to JVM's erasure.

Examples with TypeTag can get quite complex -- not even comparing two type tags is not exactly simple, as can be seen below:

import scala.reflect.runtime.universe.TypeTag
def f[A, B](a: A, b: B)(implicit evA: TypeTag[A], evB: TypeTag[B]) = evA == evB
type X = Int
val x: X = 5
val y = 5
f(x, y) // false, X is not the same type as Int

Of course, there are ways to make that comparison return true, but it would require a few book chapters to really cover TypeTag, so I'll stop here.

Finally, maybe you don't care about the type of the variable at all. Maybe you just want to know what is the class of a value, in which case the answer is rather simple:

val x = 5
x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it

It would be better, however, to be more specific about what you want to accomplish, so that the answer can be more to the point.

Solution 2:

I think the question is incomplete. if you meant that you wish to get the type information of some typeclass then below:

If you wish to print as you have specified then:

scala>  def manOf[T: Manifest](t: T): Manifest[T] = manifest[T]
manOf: [T](t: T)(implicit evidence$1: Manifest[T])Manifest[T]

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> println(manOf(x))
scala.collection.immutable.List[Int]

If you are in repl mode then

scala> :type List(1,2,3)
List[Int]

Or if you just wish to know what the class type then as @monkjack explains "string".getClass might solve the purpose

Solution 3:

If by the type of a variable you mean the runtime class of the object that the variable points to, then you can get this through the class reference that all objects have.

val name = "sam";
name: java.lang.String = sam
name.getClass
res0: java.lang.Class[_] = class java.lang.String

If you however mean the type that the variable was declared as, then you cannot get that. Eg, if you say

val name: Object = "sam"

then you will still get a String back from the above code.

Solution 4:

i have tested that and it worked

val x = 9
def printType[T](x:T) :Unit = {println(x.getClass.toString())}

Solution 5:

instance.getClass

above method return path of instance's Class. to get the exact Class name of the instance, try this:

instance.getClass.getSimpleName

here is the example: enter image description here