zer*_*323 16 generics scala classcastexception scala-option scala-generics
可以说我有一个像这样的数组*:
val foo: Any = 1 : Int
Option(foo.asInstanceOf[String])
Run Code Online (Sandbox Code Playgroud)
由于显而易见的原因失败:
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
Run Code Online (Sandbox Code Playgroud)
接下来让我们考虑以下类:
case class DummyRow() {
val foo: Any = 1 : Int
def getAs[T] = foo.asInstanceOf[T]
def getAsOption[T] = Option(foo.asInstanceOf[T])
}
Run Code Online (Sandbox Code Playgroud)
至于我可以告诉大家getAs应该的行为方式与以前一样apply,然后asInstanceOf.
令人惊讶的是事实并非如此.单独调用时会抛出异常:
DummyRow().getAs[String]
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
Run Code Online (Sandbox Code Playgroud)
但当Option成功包装时:
val stringOption = Option(DummyRow().getAs[String])
// Option[String] = Some(1)
DummyRow().getAsOption[String]
// Option[String] = Some(1)
Run Code Online (Sandbox Code Playgroud)
并且只有在我尝试访问包装值时才会失败:
stringOption.get
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?它似乎有限,ClassCastException所以我猜它与类型擦除等一些丑陋的东西有关.
*Any并asInstanceOf在那里模仿的第三方代码的行为,所以请让我们不要纠缠于这一点.
**在Scala 2.10.5,2.11.7中测试过
***如果您对上下文感兴趣,可以查看在scala中使用包含 - 异常
****评论中链接的其他相关问题:
以下是您的问题的简化版本,附加案例 Any
def getAs[T] = (1:Int).asInstanceOf[T]
//blows up
getAs[String]
//blows up
def p(s:String): Unit = {}
p(getAs[String])
//works
def p[T](s:T): Unit = {}
p(getAs[String])
//works
def p(s:Any): Unit = {}
p(getAs[String])
Run Code Online (Sandbox Code Playgroud)
因为您使用泛型参数创建方法,所以运行时不需要"触摸"该值,因为它不关心.通用将被视为Any/ Object在运行时.