我想在运行时获得一个variables的types
我想在运行时获得一个variables的types。 我如何做到这一点?
所以,严格来说,“variables的types”总是存在的,可以作为typesparameter passing。 例如:
val x = 5 def f[T](v: T) = v f(x) // T is Int, the type of x
但取决于你想做什么 ,这不会帮助你。 例如,可能不想知道variables的types是什么,但要知道值的types是否是某种特定的types,比如:
val x: Any = 5 def f[T](v: T) = v match { case _: Int => "Int" case _: String => "String" case _ => "Unknown" } f(x)
这里variablesAny
的types是什么都没有关系。 重要的是,检查的是5
的types,价值。 事实上, T
是没用的 – 你也可以写下def f(v: Any)
。 此外,它使用ClassTag
或值的Class
,这将在下面解释,并且不能检查types的types参数:您可以检查是否某个List[_]
(某个List[_]
),而不是它是否为例如, List[Int]
或List[String]
。
另一种可能是你想要确定variables的types。 也就是说,你想将types转换为一个值,所以你可以存储它,传递它等。这涉及到reflection,你将使用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
收到的types参数。 这不会工作:
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
,它与上一个ClassTag
示例中的隐式参数一样工作,但使用了一个匿名variables。
我们也可以从一个值的Class
获得一个ClassTag
,像这样:
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
ClassTag
是有限的,它只覆盖基类,但不包括types参数。 也就是说, List[Int]
和List[String]
的ClassTag
是相同的List
。 如果您需要types参数,则必须使用TypeTag
。 然而, TypeTag
不能从一个值获得,也不能用于模式匹配,因为JVM的擦除 。
TypeTag
例子TypeTag
会变得相当复杂 – 即使比较两个types标签也不是很简单,如下所示:
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
当然,还有一些方法可以使这种比较成为可能,但是这需要一些书本章来真正涵盖TypeTag
,所以我会在这里停下来。
最后,也许你根本不关心variables的types。 也许你只是想知道什么是价值的阶级,在这种情况下,答案很简单:
val x = 5 x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it
然而,要更加具体地说明你想要完成什么,那么答案就更重要了。
我认为这个问题是不完整的。 如果你的意思是你想获得一些typestypes的信息,那么下面是:
如果您希望按照您的指定进行打印,则:
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]
或者如果你只是想知道什么类的types,然后@monkjack解释"string".getClass
可能会解决的目的
如果通过variables的types来表示variables所指向的对象的运行时类,那么可以通过所有对象所具有的类引用来获得该variables。
val name = "sam"; name: java.lang.String = sam name.getClass res0: java.lang.Class[_] = class java.lang.String
如果你的意思是variables声明的types,那么你不能得到这个。 例如,如果你说
val name: Object = "sam"
那么你仍然会从上面的代码中得到一个String
。
我已经testing,它的工作
val x = 9 def printType[T](x:T) :Unit = {println(x.getClass.toString())}