为什么使用Option包装泛型方法调用推迟ClassCastException? [英] Why wrapping a generic method call with Option defers ClassCastException?
问题描述
可以说我有这样一个数组*:
val foo:Any = 1:Int
Option (foo.asInstanceOf [String])
失败的原因很明显:
// java.lang.ClassCastException:java.lang.Integer不能转换为
// java.lang.String
/ / ... 48消除
接下来让我们考虑以下类:
case class DummyRow(){
val foo:Any = 1:Int
def getAs [T] = foo.asInstanceOf [T]
def getAsOption [T] = Option(foo.asInstanceOf [T])
}
据我所知, getAs
的行为应该与前面的 apply 然后跟着
asInstanceOf
。
令人惊讶的是,情况并非如此。如果单独调用,它将抛出一个异常:
$ p $ D $ D $ get $ [
// java.lang。 ClassCastException:java.lang.Integer不能转换为
// java.lang.String
// ... 48消除
,但当用选项
包装成功时:
val stringOption = Option(DummyRow()。getAs [String])
// Option [String] =一些(1)
DummyRow()。getAsOption [String ]
// Option [String] =有些(1)
尝试访问被包装的值:
stringOption.get
// java.lang.ClassCastException:java.lang.Integer不能转换为
// java.lang.String
// ... 48消除
那么这里发生了什么?它似乎是有限的 ClassCastException
,所以我想它与一些丑陋的东西,如类型擦除。
* 任何
和 asInstanceOf
都可以模仿第三方代码的行为所以请不要纠缠于此。
**测试Scala 2.10.5,2.11.7
***如果您对上下文感兴趣,可以查看在scala中使用包含 - 异常
****其他相关问题与评论链接:
以下是您的问题的简化版本,其中任何
def getAs [T] =(1:Int).asInstanceOf [T]
//爆炸
getAs [String]
//炸毁
def p(s:String):Unit = {}
p(getAs [String])
//作品
def p [T](s:T):Unit = {}
p(getAs [String])
// works
def p(s:Any):Unit = {}
p(getAs [String])
因为您使用通用参数创建方法,所以运行时不需要触摸值,因为它不关心。在运行时,Generic将被视为任何
/ Object
。
Lets say I have an array like this*:
val foo: Any = 1 : Int
Option(foo.asInstanceOf[String])
which fails for obvious reason:
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
Next lets consider a following class:
case class DummyRow() {
val foo: Any = 1 : Int
def getAs[T] = foo.asInstanceOf[T]
def getAsOption[T] = Option(foo.asInstanceOf[T])
}
As far as I can tell getAs
should behave the same way as the previous apply
followed by asInstanceOf
.
Surprisingly it is not the case. When called alone it throws an exception:
DummyRow().getAs[String]
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
but when wrapped with Option
succeeds:
val stringOption = Option(DummyRow().getAs[String])
// Option[String] = Some(1)
DummyRow().getAsOption[String]
// Option[String] = Some(1)
and fails only when I try to access wrapped value:
stringOption.get
// java.lang.ClassCastException: java.lang.Integer cannot be cast to
// java.lang.String
// ... 48 elided
So what happens here? It seems to be limited ClassCastException
so I guess it is related to some ugly thing like type erasure.
* Any
and asInstanceOf
are there to mimic a behavior of the 3rd party code so please lets not dwell on that.
** Tested in Scala 2.10.5, 2.11.7
*** If you're interested in the context you can take a look at Using contains in scala - exception
**** Other relevant questions linked in the comments:
- Why does `.asInstanceOf` sometimes throw, and sometimes not?,
- Why asInstanceOf doesn't throw a ClassCastException?
Below is a simplified version of your problem with an additional case for 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])
Because you create a method with a generic parameter, the runtime doesn't need to "touch" the value because it does not care. Generic will be treated as Any
/Object
at runtime.
这篇关于为什么使用Option包装泛型方法调用推迟ClassCastException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!