Я хочу получить тип переменной во время выполнения

Я хочу получить тип переменной во время выполнения. Как мне это сделать?

Итак, строго говоря, «тип переменной» всегда присутствует и может быть передан как параметр типа. Например:

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 Value, которые объясняются ниже, и не могут проверять параметры типа типа: вы можете проверить, является ли что-то List[_] ( List of something), но не является ли оно для например, List[Int] или List[String] .

Другая возможность заключается в том, что вы хотите подтвердить тип переменной. То есть вы хотите преобразовать тип в значение, чтобы вы могли его сохранить, передать его и т. Д. Это включает в себя 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 . Это не сработает:

 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 , но использует анонимную переменную.

Также можно получить ClassTag из Class Value, например:

 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 ограничен тем, что он охватывает только базовый class, но не его параметры типа. То есть, ClassTag для List[Int] и List[String] тот же, List . Если вам нужны параметры типа, то вместо этого вы должны использовать TypeTag . Однако TypeTag не может быть получен из значения и не может использоваться при сопоставлении шаблонов из-за стирания JVM.

Примеры с 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 

Конечно, есть способы сделать это сравнение верным, но для того, чтобы действительно охватить TypeTag , потребуется несколько глав TypeTag , поэтому я остановлюсь здесь.

Наконец, может быть, вам вообще не нужен тип переменной. Возможно, вы просто хотите знать, что такое class значения, и в этом случае ответ довольно прост:

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

Было бы лучше, однако, более конкретно о том, чего вы хотите достичь, чтобы ответ мог быть более точным.

Я думаю, что вопрос неполный. если вы имели в виду, что хотите получить информацию о типе некоторого типа, ниже:

Если вы хотите напечатать, как вы указали, тогда:

 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] 

Или, если вы просто хотите узнать, что тип classа, то как @monkjack объясняет "string".getClass может решить цель

Если по типу переменной вы подразумеваете class времени выполнения объекта, на который указывает переменная, вы можете получить это через ссылку на class, которую имеют все объекты.

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

Если вы, однако, имеете в виду тип, который была объявлена ​​переменной, тогда вы не сможете это получить. Например, если вы говорите

 val name: Object = "sam" 

то вы по-прежнему получите String из вышеуказанного кода.

Я тестировал это, и он работал

 val x = 9 def printType[T](x:T) :Unit = {println(x.getClass.toString())} 
  • Исправляемые значения искры из строки
  • scala slick метод, который я пока не понимаю
  • Что такое контекст Scala и границы обзора?
  • Редактор не содержит основного типа
  • Spark: производить RDD всех возможных комбинаций из RDD
  • Синтаксис сахара: _ * для лечения Seq как параметры метода
  • Что такое аннотация Scala для оптимизации рекурсивной функции хвоста?
  • как сделать saveAsTextFile НЕ разделить вывод на несколько файлов?
  • Возврат исходного типа коллекции в общий метод
  • Как вызвать метод Scala Object с использованием отражения?
  • Несоответствие типа Scala для понимания
  • Давайте будем гением компьютера.