我想在運行時獲取變量的類型。 我該怎麼做?我想在運行時獲取變量的類型
回答
所以,嚴格地說,「類型變量「總是存在的,並且可以作爲類型參數傳遞。例如:
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[_]
(List
),但不是它是否是例如List[Int]
或List[String]
。
另一種可能是你想reify變量的類型。也就是說,你想將類型轉換爲一個值,所以你可以存儲它,傳遞它等。這涉及到反射,你將使用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
例子的隱含參數,但使用匿名變量。
你也可以從一個值的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
是有限的,因爲它僅覆蓋了基礎類,但不是它的類型參數。也就是說,ClassTag
對於List[Int]
和List[String]
是相同的,List
。如果您需要類型參數,則必須改用TypeTag
。但是,由於JVM的刪除,無法從值中獲得A TypeTag
,也不能用於模式匹配。
與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
當然,也有辦法讓那個比較返回true,但它需要幾本書章節來真正涵蓋TypeTag
,所以我會在這裏停下來。
最後,也許你根本不關心變量的類型。也許你只是想知道什麼是類的值,在這種情況下,答案很簡單:
val x = 5
x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it
這將是更好的,但是,更具體的瞭解你想要完成的任務,從而使答案可能更重要。
如果通過變量的類型您指的是變量指向的對象的運行時類,那麼您可以通過所有對象具有的類引用來獲得此類。
val name = "sam";
name: java.lang.String = sam
name.getClass
res0: java.lang.Class[_] = class java.lang.String
如果你的意思是變量被聲明爲的類型,那麼你不能得到那個。例如,如果你說
val name: Object = "sam"
那麼你仍然會得到一個String
從上面的代碼後面。
你也可以做'name.getClass.getSimpleName'一個更可讀的輸出 –
我認爲這個問題並不完整。如果你的意思是,你希望得到一些類型類,然後下面的類型的信息:
如果你想打印爲您指定然後:
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
可能會解決這個目的
我已經測試和它的工作
val x = 9
def printType[T](x:T) :Unit = {println(x.getClass.toString())}
- 1. 在運行時知道類型變量
- 2. 在運行時更改變量類型
- 3. 運行時的C++變量類型
- 4. 在運行時獲取模板類型
- 5. 如何在Kotlin中獲取變量的運行時類?
- 6. 運行時更改變量類型
- 7. 在MySQL中獲取變量的類型
- 8. 運行時獲取輸入類型
- 9. 類變量類型獲取我的視圖控制器改變
- 10. 獲取使用TypeBuilder在運行時創建的類的類型
- 11. 在運行時獲取非泛型IDictionary的鍵和值類型
- 12. 如何在Java中獲取類型變量的類型泛型
- 13. 覈對聯盟類型的變量在運行時在Python 3.6
- 14. 如何在運行時確定變量的類型
- 15. 是否可以在運行時更改AngularJS變量的類型?
- 16. 將變量轉換爲僅在運行時已知的類型?
- 17. 根據運行時變量的類型創建通用類
- 18. 在運行時獲取列表的項目類型在c#
- 19. 在運行時設置矢量類型
- 20. 如何在運行時檢查變量類型在Go語言
- 21. 獲取鍵盤類型的變量
- 22. 獲取Kotlin中變量的類型
- 23. 獲取變量類型的AutoHotkey
- 24. 獲取不同類型的變量
- 25. 在運行時獲取編譯時變量
- 26. 在運行時使用Dlang中的反射獲取變量值
- 27. 在oracle中的運行時變量中獲取值
- 28. 運行時在彙編語言中獲取變量的大小
- 29. C#在運行時獲取定義字典的類型
- 30. 在運行時獲取對象的父類型
你寫後的示例代碼「但是,這將:」令人困惑。它編譯,但結果不是你在評論中顯示的結果。這兩個調用返回相同的結果:「A是B」。因爲值'5'既是「Int」的實例又是「Any」的實例。 除此之外,你的解釋是完美:) – Readren
@Readren值沒有測試,類是。 「Int」是「Any」,但「Any」不是「Int」。它適用於Scala 2.10,它應該適用於Scala 2.11,我不知道它爲什麼不是。 –
它讓我害怕與你一樣的矛盾,但代碼'一個匹配{case _:B => ...'測試變量'a'的實際值的類型,而不是變量的類型'a '。 你是對的,它返回你在scala 2.10.6中說的話。但它應該是一個錯誤。 在scala 2.11.8中,應該測試實際值的類型。 – Readren