在这些情况下,Scala 值类将被“装箱”,对吧?

2023-11-26

如果我有这个值类:

class ActionId(val value: Int) extends AnyVal

那么,在下面的所有示例中,都会为值类分配一个对象吗? (它将被“装箱”——它将not只需将其解包为普通的 32 位整数,对吧?)

  1. 返回值类的函数 - 值类逃逸范围并因此被“装箱”?

    def someFunction(): ActionId = {
      ...
      return ActionId(123)
    }
    
  2. 一个返回的函数具有值类成员的对象— 值类脱离了范围并因此被“装箱”?

    case class Post(id: ActionId, ...) { ... }
    
    def someFunction(): Post = {
      ...
      val somePost = Post(ActionId(123), ...) // ActionId will be "boxed", right?
      return somePost
    }
    
  3. Even if 具有值类成员的对象 is not返回(并没有真正逃脱范围),当值类用作另一个类的成员(作为Post类,在本例中)?

    def anotherFunction() {
      ...
      val somePost = Post(ActionId(123), ...) // "Boxed" here too, right?
    
      // ... do something with somePost
    
      // But don't:  return somePost
    
      // However some *other* similar functions *do* return `somePost` — so
      // class `Post` must be able to box the ActionId? Hence it's boxed (above)?
    }
    

与此相关的是这个答案,这说明了当值类没有逃逸范围时,它实际上被内联了。参考Scala Improvement Process文档SIP-15更多细节。然而,据我所知,SIP-15 实际上并没有提到逃逸范围的值类实例将被“装箱”。但我认为它必须被“装箱”似乎是合理的。 (为什么SIP没有明确说明如果逃逸就会被装箱?)


你的例子都没有导致拳击。值类仅与泛型、数组一起装箱,并且当键入为超类/特征时(例如 Any/AnyVal)

它们用泛型装箱,否则你无法将它们与值区分开来(而且基元无论如何都需要一个盒子)。 Any 也同样处理,其他超类/特征需要一个框,否则类型关系是错误的。

它们用数组装箱,因为数组需要知道内容的类型,但 JVM 不理解“值类型”的概念。所以你最终会得到一个数组,它表示它是被装箱的类型,但 Scala 假装是值类型的数组;我们做出了一个决定(基于之前 Array 的问题,当时它不仅仅是一个普通的 Java/JVM 数组),这将导致太多微妙的错误和极端情况。

以下是获得拳击的三种方法的示例:

trait Q extends Any {}
class X(val x: String) extends AnyVal with Q {}

// Array
val a = Array(new X("salmon"))   // boxed

// Generic
val b = Option(new X("minnow"))  // boxed

// Upcast
val c = (new X("perch"): Any)    // boxed
val d = (new X("cod"): AnyVal)   // boxed
val e = (new X("herring"): Q)    // boxed

其他所有内容(通过各种函数等传递)都不需要装箱,包括您的所有示例。

数组是一种特殊情况,因为您可以存储基元并将它们作为值类再次取出,字节码开销为零,但语法开销很大:

class Y(val repr: String) extends AnyVal {}
val y1 = new Y("apple")    // unboxed
val y2 = new Y("orange")   // unboxed
val ys: Array[String] = Array(y1.repr, y2.repr)   // no overhead
val y3 = new Y(ys(0))      // no overhead
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在这些情况下,Scala 值类将被“装箱”,对吧? 的相关文章

随机推荐

  • Android setX() 和 setY() 行为怪异

    我正在尝试动态创建然后在 Android 活动中移动图像 但是 setX 和 setY 方法似乎无法正常工作 它在首次创建和放置图像时正确设置图像的位置 但任何更新图像的尝试都会导致图像被放置在错误的位置 例如 图像在以下代码上移动 Ima
  • cqlsh 连接错误:“ref() 不接受关键字参数”

    我已经尝试了所有措施这个帖子 and 卡桑德拉文档 我尝试运行所有版本的 Cassandra 包括 tarball 和 Debian 软件包中的最新版本 3 7 但执行时不断出现错误cqlsh Error 连接错误 无法连接到任何服务器 1
  • 使用变量作为键访问 Ruby 哈希

    如果我有以下 ruby 哈希 environments testing gt 11 22 33 44 production gt 55 66 77 88 我如何访问上述哈希的部分内容 下面的例子说明了我想要实现的目标 current env
  • Discord 机器人 - “属性错误:‘NoneType’对象没有属性‘strip’。

    我是一名新编码员 我一直在关注tutorial关于如何使用下面的代码创建一个不和谐的机器人 实际上已经直接从教程中复制了代码 并且我创建了一个 env 文件来存储我的 AuthToken 每次运行代码时 我都会收到上述代码下方的错误 有小费
  • 未找到 Android Studio Gradle DSL 方法:“android()”--错误(17,0)

    我尝试在 Android Studio 中运行我的项目 但出现以下错误 我跟踪了许多消息来源只是为了让它运行并最终来到这里 但不知道还能做什么 我该如何配置这个项目来运行 构建 gradle Top level build file whe
  • gdb 通过走帧指针进行回溯

    有时会出现一些小的堆栈损坏 导致 gdb 无法执行 回溯 我创建了以下 gdb 宏 x86 64 可以轻松地使其适用于 x86 该宏取决于关闭 omit frame pointer 即 fno omit frame pointer 并向我展
  • Python拒绝多次迭代文件中的行[重复]

    这个问题在这里已经有答案了 我正在编写一个程序 需要我多次迭代文件的每一行 loops 0 file open somefile txt while loops lt 5 for line in file print line loops
  • 使用 php 更改 css 值

    如何更改在我的主页上从管理区域显示一些文本的 div 的 css 我希望当我在插件管理页面中输入颜色代码时 该代码会在 css 文件中更新 这是很平常的事 却无法把握 这是我的 div 的 css div background 0000 这
  • 如何在 PHP 中使用 Graph API 使用 message_tags 字段发布消息

    我想使用 Graph API 发布带有 message tags 的消息 我确认消息仅在 PHP 中发布 但不适用于 message tags 这是示例代码
  • javascript - 为什么有同步和异步模块的规范?

    我刚刚读完这篇文章article在 Javascript 模块上 我可以理解CommonJS模块是同步加载的 而AMD模块是异步加载的 我不明白的是我怎样才能模块变成神奇地同步如果我以 CommonJS 格式编写它 或者如果我以 Commo
  • 角度表单验证以验证电话号码

    我正在尝试使用角度中的正则表达式来验证电话号码 HTML 内容 div class form group row div
  • SetStdHandle 对 cout/printf 没有影响

    标题说明了一切 当我运行以下代码时 HANDLE hOut GetStdHandle STD OUTPUT HANDLE HANDLE hFile CreateFile TEXT Foo txt GENERIC WRITE FILE REA
  • Perl 中的标量上下文和列表上下文有什么区别?

    Perl 中的标量上下文和列表上下文有什么区别 这在其他语言 例如 Java 或 Javascript 中是否有相似之处 Perl 中的各种运算符都是上下文相关的 并且在列表和标量上下文中产生不同的结果 例如 my array 1 2 4
  • 强制对 js 或 axios 使用不同的用户代理

    我通过 axios get 和 post 请求路由所有请求 我正在测试一些 iframe 它们检测用户代理 并根据它是什么代理 它们更改有效负载和样式等 例如 如果我通过切换设备工具栏并设置为 iphone 在开发工具上更改它 则所有请求都
  • XMLHttpRequest 从远程主机获取 HTTP 响应

    为什么下面的代码基于 Mozilla 示例不起作用 尝试使用 Firefox 3 5 7 和 Chrome
  • 如何查看除特定控件之外的所有 FormControls ValueChanges?

    我有一个表单 每当控制输入值发生变化时就会进行计算 这是我的form group好像 form group this fb group control1 control2 control3 control10 我可以通过以下方式检测所有控件
  • C# 默认参数

    对于某人来说 这可能是一个非常简单的答案 我有一个方法Optional Parameter像这样 public static Email From string emailAddress string name var email new
  • 返回指向局部变量的指针[重复]

    这个问题在这里已经有答案了 我不知道为什么这有效 由于 x 是一个局部变量 我认为当我尝试返回它时会收到错误 然而 第一个 printf 工作正常 但随后它只打印出 0 任何人都可以解释这里发生了什么吗 include
  • 方向改变时不调用 onCreateLoader

    我的问题与此基本相同 有时调用initLoader后没有得到onCreateLoader回调 我有2个ListFragments包含在一个ViewPager 它们一开始加载正常 但是当我改变方向时 initLoader方法不调用onCrea
  • 在这些情况下,Scala 值类将被“装箱”,对吧?

    如果我有这个值类 class ActionId val value Int extends AnyVal 那么 在下面的所有示例中 都会为值类分配一个对象吗 它将被 装箱 它将not只需将其解包为普通的 32 位整数 对吧 返回值类的函数