斯卡拉:谁能解释一下?
发布时间:2020-12-16 09:39:36 所属栏目:安全 来源:网络整理
导读:请考虑以下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[Un
请考虑以下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? [spoiler]这是一个ClassCastException;谁可以解释为什么它不被抓住并被IllegalArgumentException替代? PS:为了抢占任何问题,我为什么要这样做:这是一些使用json4s将某些字符串解析成Option [T]的代码的简化版本。如果解析失败,则返回None,如果T为Unit,则为OK,如果T为其他类型则为OK。 解决方法
说明
异常不在这里抛出: ().asInstanceOf[T] 因为这是一个未经检查的转换 – JVM无法验证是否可以将()转换为T,因为它没有关于T的类型擦除信息。 相反,这里抛出异常 Data[Integer](None).get 因为get的结果被转换为整数,这是JVM可以验证的。所以,ClassCastException实际上是在get之外抛出的。 BTW,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(()) } } Hackaround 对于这种用例,您可以直接检查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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |