Scala:谁能解释一下?

Posted

技术标签:

【中文标题】Scala:谁能解释一下?【英文标题】:Scala: who can explain this? 【发布时间】:2013-09-12 19:47:46 【问题描述】:

考虑以下 Scala 代码:

case class Data[T](value: Option[T]) 
  def get: T = try 
    doGet
   catch 
    case e: Exception => throw new IllegalArgumentException
  

  def doGet: T = value match 
    case Some(v) => v
    case None => ().asInstanceOf[T]
  


Data[Unit](None).get
Data[Integer](None).get // which exception is thrown here?

[剧透]这是一个ClassCastException;谁能解释为什么它没有被IllegalArgumentException 捕获和替换?

PS:为了抢占我为什么要这样做的任何问题:这是一些代码的简化版本,它使用 json4s 将一些字符串解析为Option[T];如果解析失败则返回None,如果TUnit 则可以,如果T 是其他类型则不可以。

【问题讨论】:

【参考方案1】:

说明

这里没有抛出异常:

().asInstanceOf[T]

因为这是一个未经检查的转换 - JVM 无法验证是否可以将 () 转换为 T,因为由于类型擦除,它没有关于 T 的信息。

相反,这里抛出异常

Data[Integer](None).get

因为get 的结果被转换为Integer,这是 JVM 可以验证的。所以,ClassCastException 实际上被抛到了get 之外。

顺便说一句,javac 总是警告未经检查的演员表,我不知道为什么 scalac 没有。

解决方法

在某种程度上,可以使用ClassTag 和基于反射的转换来解决类型擦除问题:

import scala.reflect.ClassTag, classTag

case class Data[T: ClassTag](value: Option[T]) 
  def get: T = try 
    doGet
   catch 
    case e: Exception => throw new IllegalArgumentException
  

  def doGet: T = value match 
    case Some(v) => v
    case None => classTag[T].runtimeClass.asInstanceOf[Class[T]].cast(())
  

解决方法

对于这个用例,您可以直接检查ClassTag

scala> case class Data[T](value: Option[T])(implicit t: ClassTag[T]) 
     | def get: T = value getOrElse (t match 
     |   case ClassTag.Unit => ().asInstanceOf[T]
     |   case _ => throw new IllegalArgumentException
     | )
     | 
defined class Data

scala> Data[Unit](None)
res6: Data[Unit] = Data(None)

scala> .get

scala> Data[Int](None).get
java.lang.IllegalArgumentException

【讨论】:

啊哈!擦除!这就是关键。 能否修改代码使get抛出异常? 请注意,如果您尝试这种基于反射的强制转换,例如,将List[Int] 转换为List[String],您的ClassTag 解决方法将不起作用。它会默默工作,然后失败,再次抛出ClassCastExceptionruntimeClass 不返回 Class[T] 是有原因的。 ClassTag hackaround 在这种情况下效果很好,因为只有 Unit 类型需要特殊处理,所有其他类型(包括参数化类型)都应该导致 IllegalArgumentException。也可以将implicit ClassTag 移动到get 定义中。

以上是关于Scala:谁能解释一下?的主要内容,如果未能解决你的问题,请参考以下文章

谁能解释一下预定义的 GenericModel 类的这种语法? [复制]

这道题能解释一下吗?

谁能解释一下这个 NSPredicate 语法

DAO是啥啊?谁能帮忙解释一下??

谁能解释一下 vuetify 主题代码

我正在研究沙发底座,谁能解释一下bucket和vbucket到底是啥?