为什么使用Option包装泛型方法调用推迟ClassCastException? [英] Why wrapping a generic method call with Option defers ClassCastException?

查看:141
本文介绍了为什么使用Option包装泛型方法调用推迟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:

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆