2015-10-15 85 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]' –

相关问题