2015-10-15 95 views
0
scala> def g[T] = 1.asInstanceOf[T] 
g: [T]=> T 

scala> g[String] 
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 
    ... 32 elided 

scala> { g[String]; 1 } 
res0: Int = 1 

但是:1.asInstanceOf [T]爲什麼不拋出ClassCastException?

scala> def f = 1.asInstanceOf[String] 
f: String 

scala> { f; 1 } 
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 
    at .f(<console>:7) 
    ... 32 elided 

什麼是這裏的邏輯是什麼?如何在類型參數化函數中觸發ClassCastException

+0

http://www.scala-lang.org/api/current/index.html#[email protected][T0]:T0 –

+0

但我鑄造到'字符串',而不是參數類型。 Scala文檔中有關刪除類型的評論顯然不適用。 –

回答

1

此警告回答我的問題:

scala> def g[T] = 1.isInstanceOf[T] 
<console>:7: warning: abstract type T is unchecked since it is eliminated by erasure 
     def g[T] = 1.isInstanceOf[T] 
           ^

所以asInstanceOf[T]是一個編譯時施放。它在運行時不起作用。在我得到ClassCastException的情況下,它不是由asInstanceOf[T]引發的,而是由函數外部發生的實際轉換引起的。

解決方案是採取ClassTag並使用classTag[T].runtimeClass.cast。這雖然表現略有不同:您可以在Int上使用asInstanceOf[Double],但cast將失敗,並顯示ClassCastException。解決這個問題的方法是使用Apache commons-langClassUtils.isAssignable

+0

https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#type-safe-cast Java反射不是Scala反射。爲了保證類型安全,請使用TypeTag。 ClassTag讓你創建數組。這取決於你想要安全完成的事情。 –

+0

謝謝,我不知道無形!看起來很有趣。但我不太明白其他意見。我如何用TypeTag做到這一點? –

+0

你想避免丟失類型安全性,所以傳入類型標記'def g [T:TypeTag]' –

相關問題