我嘗試獲取一個類擴展使用的所有特征的名稱,getInterfaces它回傳一個特征名稱陣列。當我手動訪問陣列的每個成員時,該方法getName回傳像這樣的簡單名稱
trait A
trait B
class C() extends A, B
val c = C()
val arr = c.getClass.getInterfaces
arr(0).getName // : String = A
arr(1).getName // : String = B
但是,當我map在arr. 結果陣列包含特征名稱的神秘版本
arr.map(t => t.getName) // : Array[String] = Array(repl$.rs$line$1$A, repl$.rs$line$2$B)
這個問題的目標不是關于如何獲取包含簡單名稱的結果陣列(為此,我可以使用arr.map(t => t.getSimpleName).)我很好奇的是為什么手動訪問陣列并使用 amap不會產生兼容的結果. 我認為這兩種方式是等價的,我錯了嗎?
uj5u.com熱心網友回復:
我相信你在 Scala REPL 或 Ammonite 中運行東西。
當你定義:
trait A
trait B
class C() extends A, B
classes A,B并且C沒有在根包的頂層定義。REPL 創建一些隔離環境,編譯代碼并將結果加載到一些內部“匿名”命名空間中。
除非這不是真的。創建此位元組碼的位置反映在類名中。所以顯然有一些類似(不一定相同)的東西
// repl$ suggest object
object repl {
// .rs sound like nested object(?)
object rs {
// $line sounds like nested class
class line { /* ... */ }
// $line$1 sounds like the first anonymous instance of line
new line { trait A }
// import from `above
// $line$2 sounds like the second anonymous instance of line
new line { trait B }
// import from above
//...
}
}
這是因為范圍界定在 REPL 中的作業方式:新行創建了一個新范圍,其中包含以前的定義并添加了新定義(可能會掩蓋一些舊定義)。這可以通過創建一段新代碼作為新匿名類的代碼、編譯它、讀入類路徑、實體化和匯入其內容來實作。通過將每一行放入單獨的類 REPL 中,可以逐步編譯和運行東西,而無需等待您告訴它腳本已完成并關閉。
當您使用運行時反射訪問類名時,您會看到如何評估事物的工件。一條路徑可能會通過隱藏這些東西的 REPL 美化器,而另一條則繞過它們,以便您看到 JVM 看到的原始值。
uj5u.com熱心網友回復:
問題不map在于 with Array,尤其是它的toString方法(這是不使用 的眾多原因之一Array)。
實際上,在這種情況下,情況更糟,因為 REPL 做了一些奇怪的事情來嘗試漂亮地列印Arrays,在這種情況下效果不佳(而且,恕我直言,只會增加混亂)
您可以直接呼叫解決此問題mkString,例如:
val arr = c.getClass.getInterfaces
val result = arr.map(t => t.getName)
val text = result.mkString("[", ", ", "]")
println(text)
但是,我寧愿建議根本不使用,而是盡快Array將其轉換為適當的集合(例如List) ,例如:
val interfaces = c.getClass.getInterfaces.toList
interfaces .map(t => t.getName)
注意:關于不使用的其他原因
Arrays
- 它們是可變的。
- 是不變的。
- 它們不是集合層次結構的一部分,因此您不能在通用方法上使用它們(嗯,您實際上可以,但這需要更多技巧)。
- 它們
equals是通過參考而不是通過值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/417417.html
標籤:
