我想在运行时获取变量的类型

时间:2013-10-15 17:06:07

标签: scala reflection

我想在运行时获取变量的类型。 我该怎么做?

5 个答案:

答案 0 :(得分:118)

因此,严格地说,“变量的类型”始终存在,并且可以作为类型参数传递。例如:

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

但根据你想要做什么 ,这对你没有帮助。例如,可能想知道变量的类型是什么,但要知道的类型是否是某种特定类型,例如:

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

这里变量的类型Any无关紧要。重要的是,检查的是值5的类型。实际上,T是无用的 - 您可能也会将其编写为def f(v: Any)。此外,它使用ClassTag或值Class,如下所述,并且无法检查类型的类型参数:您可以检查某些内容是否为List[_]({{1 (例如,ListList[Int]

另一种可能性是你希望 reify 变量的类型。也就是说,您希望将类型转换为值,因此您可以存储它,传递它等等。这涉及反射,您将使用List[String]ClassTag。例如:

TypeTag

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" 还允许您使用在ClassTag上收到的类型参数。这不起作用:

match

但这会:

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

这里我使用的是上下文边界语法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) ,它的作用与上一个B : ClassTag示例中的隐式参数类似,但使用的是匿名变量。 / p>

还可以从值ClassTag获取ClassTag,如下所示:

Class

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 的局限性在于它只涵盖基类,而不是其类型参数。也就是说,ClassTagClassTag的{​​{1}}是相同的,List[Int]。如果您需要类型参数,则必须使用List[String]。但是,由于JVM的擦除,无法从值获取List,也无法在模式匹配中使用{<1}}。

TypeTag的示例可能变得相当复杂 - 甚至不比较两个类型标签也不是很简单,如下所示:

TypeTag

当然,有一些方法可以使比较返回true,但是需要一些书籍章节来真正涵盖TypeTag,所以我会在这里停下来。

最后,也许您根本不关心变量的类型。也许你只想知道一个值的类是什么,在这种情况下答案很简单:

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

然而,更好地了解您想要完成的任务,以便答案可以更加重要。

答案 1 :(得分:40)

我认为问题不完整。如果你的意思是你希望得到一些类型的类型信息,那么下面是:

如果您希望按照指定打印:

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]

如果您处于repl模式,那么

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

或者,如果您只是想知道类型类型,那么@monkjack解释"string".getClass可能会解决目的

答案 2 :(得分:16)

如果变量的类型是指变量指向的对象的运行时类,那么您可以通过所有对象具有的类引用来获取它。

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

如果你的意思是变量被声明为的类型,那么你就无法得到它。例如,如果你说

val name: Object = "sam"

然后您仍会从上面的代码中获得String

答案 3 :(得分:11)

我测试了它并且它有效

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

答案 4 :(得分:0)

instance.getClass

上面的方法返回实例的类的路径。 要获取实例的确切类名称,请尝试以下操作:

instance.getClass.getSimpleName

示例如下: enter image description here