Scala:谁能解释一下?

2023-12-28

考虑以下 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返回,如果T was Unit如果不行的话T是其他类型。


解释

这里不会抛出异常:

().asInstanceOf[T]

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

相反,这里抛出异常

Data[Integer](None).get

因为结果get被铸成Integer这是 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(())
  }
}

破解方法

对于此用例,您可以检查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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala:谁能解释一下? 的相关文章

随机推荐

  • Vue 事件处理程序的可组合函数

    我正在使用 Vue 2 0 ES6 Webpack 我有一个组件 我们称之为Parent 和几个孩子 我们称之为text input每个 每一个text input发出一个名为的事件change每一个都应该改变 Parent 内部的一个不同
  • Android Studio 错误“不支持的类文件主要版本 61”

    我将 Android Studio 项目从一台计算机移至另一台计算机 现在出现此错误 不支持的类文件主要版本 61 我怎样才能解决这个问题 在 的帮助下 罗伯特回答 https stackoverflow com a 70632872 10
  • angularjs app.run 不会被状态调用

    我根本看不出问题所在 这是我的代码 var app angular module application ui router ngResource user controllers user services app config func
  • 如何在 numba.jit 函数中测量时间?

    我想转换一个conventional loop into a numba jit内部运行并测量其进程的时间 我尝试使用time模块 但它似乎与 numba 不兼容 Code from numba import jit jitclass im
  • Ruby on Rails 错误。处理控制器方法为 png

    我已经在我的路线中给出了这个 get custom page name gt custom page load content 这是我的控制器方法 def load content page name params name split j
  • Ionic 构建时阻止 HTTPS --release android apk

    调试 apk 工作正常 这排除了通常的嫌疑 但是当我构建 签名 安装发布版本时 角度无法进行 https http API 调用 http 到同一端点 我允许调试 可以工作 科尔多瓦白名单已安装ionic plugin add cordov
  • 如何将离线 HTML5 Web 数据库与集中数据库同步

    我希望能够在 HTML5 iPad Web 应用程序中执行以下操作 将数据上传到在线数据库 如果我用 SQLite 之类的东西构建在线数据库 大小可能 将数据的子集或完整副本提取到离线网络数据库 超出3G网络覆盖范围 对下载的数据执行一系列
  • 超链接 HREF 不起作用

    我正在考虑一个新的网站想法 但是当我测试它时 A HREF 不起作用 它甚至没有显示手指 手指针 它是内容区域的文本 标题下的第一个白色块 但不是菜单 标题应该是帖子的链接 Wordpress 无效链接的屏幕截图 红色箭头 http new
  • 为什么此方法会导致代码分析错误 CA2000: Call Dispose()

    我正在使用 Microsoft Minimal Rules 代码分析集构建我的项目 它为我提供了关于此方法的 CA2000 private Timer InitializeTimer double intervalInSeconds Tim
  • 在 Git 中引用提交的子级

    如果您想移动HEAD到当前的父级HEAD 这很容易 git reset hard HEAD 但是有没有简单的方法可以执行与此操作完全相反的操作 即将头设置为当前头的第一个子提交 现在 我使用 gitk 作为解决方法 alt tab 向上箭头
  • Activeadmin 和 Formtastic:表单不响应:size

    我正在尝试格式化表单 文本字段响应某些方法 而不响应其他方法 我可以做这样的事情 f input name input html gt maxlength gt 10 f input name input html gt disabled
  • 神秘的底部边框

    我答应改变一个电子商务网站上的标志 虽然需要几分钟 但它花了很多小时 所以我希望有更多 CSS 经验的人可以帮助我 这是网站 http varuosad ee http varuosad ee 我似乎无法做到 tr 包含与图像 155px
  • Perl 6 分别捕获重复匹配组?

    我相信 Perl 6 提供了单独捕获重复组的能力 而不是早期的风格 您只能捕获最后一个组或整个匹配的组字符串 有人可以举一个很好的例子来说明如何使用 Perl 6 的这个很棒的功能吗 例如 我需要捕获此正则表达式的所有匹配组 and say
  • XPath:如何选择与同一级别的其他元素相关的元素

    问题很简单 但我对这种情况没有足够的练习 如何获得price如果我们知道我们只需要 块 中每个 div 的文本值商品促销元素 div class block div class item promo item div div class i
  • Python 上的 OpenCV 中的立体校准

    我是 OpenCV 新手 找不到 Python 上的 StereoCalibration 的正常教程 如果您有一些示例 请分享 I do single calibration for each of cameras and i have n
  • 如何针对特定活动禁用 Android 软键盘?

    我有一个包含一个 EditText 的活动 我只需要输入数字 现在 我已将 EditText 的输入类型定义为仅数字 并绘制了一个漂亮的键盘供用户使用 但是我还需要确保用户单击时不会弹出软键盘编辑文本 我尝试通过添加来通过清单隐藏键盘 an
  • 使用打开的终端 Windows 目录路径在 OSX(Snow Leopard) 中打开新的终端选项卡

    我已经在谷歌上搜索了一段时间 寻找一种简单的方法来做到这一点 但我找不到 我设置了一个自定义终端环境 zsh 其中包含各种别名和函数 以使事情变得更容易 我不断遇到的一件事是 我将快速 APPLE t 创建一个新选项卡 然后键入相对于我刚刚
  • Android - 设置应用程序的默认“打开支持的链接”选项

    如何控制默认值Open supported links到任一Ask every time or Open in this app对于我的 Android 应用程序 它发生在清单中吗 我有两个应用程序尝试接受相同的通用链接方案 理想的行为是让
  • 套接字上的 ClamAV clamd INSTREAM 出现间歇性问题

    我有一个运行 NodeJS 代码的 AWS Lambda 函数 用于将文件从 S3 流式传输到在 EC2 实例上运行的 ClamAV 一般来说 大约 75 的时间 系统可以正常工作 但经常 特别是当从不同的 Lambda 容器扫描多个文件时
  • Scala:谁能解释一下?

    考虑以下 Scala 代码 case class Data T value Option T def get T try doGet catch case e Exception gt throw new IllegalArgumentEx