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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19386964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:45:18  来源:igfitidea点击:

I want to get the type of a variable at runtime

scalareflection

提问by アレックス

I want to get the type of a variable at runtime. How do I do this?

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

回答by Daniel C. Sobral

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 valueis 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, Tis useless -- you might as well have written it def f(v: Any)instead. Also, this uses either ClassTagor 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[_](Listof something), but not whether it is, for example, a List[Int]or List[String].

在这里,变量的类型是什么并不重要,Any. 重要的是,检查的是 的类型5,值。事实上,T是没用的——你还不如写它def f(v: Any)。此外,这使用ClassTag或 值的Class,这将在下面解释,并且不能检查类型的类型参数:您可以检查某物是否是 a List[_]( Listof something),但不能检查它是否是,例如, aList[Int]List[String]

Another possibility is that you want to reifythe 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 ClassTagor a TypeTag. For example:

另一种可能性是要具体化的变量的类型。也就是说,您想将类型转换为值,以便您可以存储它、传递它等。这涉及反射,您将使用ClassTagTypeTag。例如:

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 ClassTagwill also let you use type parameters you received on match. This won't work:

AClassTag还可以让您使用在 上收到的类型参数match。这行不通:

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 boundssyntax, B : ClassTag, which works just like the implicit parameter in the previous ClassTagexample, but uses an anonymous variable.

在这里,我使用了上下文边界语法 ,B : ClassTag它的工作方式与前一个ClassTag示例中的隐式参数类似,但使用的是匿名变量。

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

还可以ClassTag从值中获取 a 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

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

AClassTag的局限性在于它仅涵盖基类,而不涵盖其类型参数。也就是说,ClassTagforList[Int]List[String]是一样的,List。如果需要类型参数,则必须使用 aTypeTag代替。TypeTag但是,由于 JVM 的擦除,A不能从值中获得,也不能用于模式匹配。

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

示例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

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.

当然,有一些方法可以使这种比较返回真,但需要几本书的章节才能真正涵盖TypeTag,所以我就到此为止。

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.

但是,最好更具体地说明您要完成的任务,以便答案更切中要点。

回答by Jatin

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

如果您处于 repl 模式,则

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

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

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

回答by monkHyman

If by the type of a variableyou 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 Stringback from the above code.

那么你仍然会String从上面的代码中得到回报。

回答by SENHAJI RHAZI Hamza

i have tested that and it worked

我已经测试过了,它奏效了

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