当作为参数传递时,属性引用 (::test) 是否相当于访问属性 ({ test }) 的函数,例如`() -> 字符串`?

2023-11-20

我开始想知道是否通过访问属性::test相当于调用{ test }或者它是否是使用反射的间接调用。

当我看到以下内容时,我想到了这个问题:如何将属性 getter 作为函数类型传递给另一个函数

虽然两者::test and { test }工作时,IDE(Intellij)设置::test to a KProperty-type 而后一种类型是() -> String当分配给变量时。所以这里有一个区别。但有效的区别是什么呢?这些是 Java 中真正的方法引用,还是访问属性的反射方式?一种变体可能会对另一种变体产生性能影响吗?

代码片段:

class Test(val test : String) {
  fun testFun(func: ()->String) : String = func()
  fun callTest() {
    testFun { test } // or (::test) // is it using reflection? are these real references?
  }
}

我认为在这种情况下最好检查字节码以了解发生了什么。

我使用了以下代码:

class Test(val test: String) {
    fun testFun(func: () -> String): Unit = TODO()
    fun callTest() {
        testFun { test }
        testFun(::test)
    }
}

For testFun { test }这是生成的字节码:

ALOAD 0
NEW Test$callTest$1
DUP
ALOAD 0
INVOKESPECIAL Test$callTest$1.<init> (LTest;)V
CHECKCAST kotlin/jvm/functions/Function0
INVOKEVIRTUAL Test.testFun (Lkotlin/jvm/functions/Function0;)V

这是字节码testFun(::test):

ALOAD 0
NEW Test$callTest$2
DUP
ALOAD 0
CHECKCAST Test
INVOKESPECIAL Test$callTest$2.<init> (LTest;)V
CHECKCAST kotlin/jvm/functions/Function0
INVOKEVIRTUAL Test.testFun (Lkotlin/jvm/functions/Function0;)V

它们看起来几乎一模一样,除了第一个正在创建一个Test$callTest$1,而第二个正在使用Test$callTest$2。还有一个额外的CHECKCAST Test在第二个“版本”中,因为Test$callTest$2正在期待一个实例Test在它的构造函数中。

那么,有什么区别$1 and $2?

Here's $1版本:

final class Test$callTest$1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0  {

    ....

    final synthetic LTest; this$0 // reference to your Test instance

    <init>(LTest;)V {
        ALOAD 0
        ALOAD 1
        PUTFIELD Test$callTest$1.this$0 : LTest;
        ALOAD 0
        ICONST_0 // Lambda arity is zero
        INVOKESPECIAL kotlin/jvm/internal/Lambda.<init> (I)V
        RETURN
    }

    public final String invoke() {
        ALOAD 0
        GETFIELD Test$callTest$1.this$0 : LTest;
        INVOKEVIRTUAL Test.getTest ()Ljava/lang/String;
    }
}

While $2:

final class Test$callTest$2 extends kotlin/jvm/internal/PropertyReference0  {

    ...

    <init>(LTest;)V {
        ALOAD 0
        ALOAD 1
        INVOKESPECIAL kotlin/jvm/internal/PropertyReference0.<init> (Ljava/lang/Object;)V
        RETURN
   }

    public Object get() {
        GETFIELD Test$callTest$2.receiver : Ljava/lang/Object;
        CHECKCAST Test
        INVOKEVIRTUAL Test.getTest ()Ljava/lang/String;
        ARETURN
    }
}

所以看起来字节码指令方面没有太大区别。

编辑: 班级$2继承了一个invoke来自其父类的方法PropertyReference0这就是所谓的get()方法,同时$1立即宣布invoke。因此,无需进一步优化$2与以下相比执行一个额外的方法调用$1.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当作为参数传递时,属性引用 (::test) 是否相当于访问属性 ({ test }) 的函数,例如`() -> 字符串`? 的相关文章

随机推荐

  • Files.walk(),计算总大小

    我正在尝试计算光盘上文件的大小 在 java 7 中 可以使用以下命令来完成文件 walkFileTree如我的回答所示here 但是 如果我想使用 java 8 流来执行此操作 它将适用于某些文件夹 但不适用于所有文件夹 public s
  • 编译时需要CUDA硬件吗?

    是否需要安装支持 CUDA 的显卡 在 Linux 中 来编译 CUDA 程序nvcc 或者可以在任何地方编译程序并只在这样的系统上运行 不 编译不需要显卡 您甚至不需要一个来运行该程序 您可以在软件中模拟它 UPDATE好吧 显然 自 C
  • PostgreSQL 选择随机行的最佳方法

    我想在 PostgreSQL 中随机选择行 我尝试了以下方法 select from table where random lt 0 01 但其他一些人推荐这个 select from table order by random limit
  • 如何使用 Papa Parse 从 CSV 文件中提取数据到 React 状态?

    我在用着帕帕 帕斯解析 CSV 文件中的图表 我想将数据存储在反应状态文件解析后 Papa Parse 不返回任何内容 结果异步提供给回调函数 此外 setState 在异步回调中不起作用 这个问题类似于从 CSV 中检索已解析的数据 我尝
  • 在 __destruct() 上更新数据库?

    你认为这是个好主意吗 假设您有一个应用程序组件 其他组件使用该组件来检索 更新数据库中的数据 它基本上是一个具有 get set update 方法的类 对于该组件来说 仅在调用时更新 或设置 其属性中的数据 并在 destruct 上更新
  • Laravel Storage::get() 不返回图像的 exif 数据

    我正在尝试获取图像 exif 数据 以便我可以使用图像干预定位功能 唯一的问题是我无法使用 Storage get 读取 exif 数据 首先 我像这样存储上传的图像 filename uniqid file gt getClientOri
  • 本机调试 Android Studio

    当我通过Genymotion运行Native调试时出现这样的错误 Starting LLDB server run as org cocos2dx cpp empty test data data org cocos2dx cpp empt
  • n 维数组/张量的数据结构,例如 A[0, :, :] 和 A[1, :, :] 可以具有不同的形状

    使用 Python Numpy 我正在处理 n 维数据 最好是在ndarray 这样 1 参差不齐的阵列 例如A 0 A 49 形状可以是 100x100 并且A 50 形状可能为 10000x10000 我不想创建形状为 10000 10
  • Android WebView 带有乱码的 UTF-8 字符。

    我在 android 应用程序中使用一些 webview 但无法使它们以 utf 8 编码显示 如果使用这个 我将看不到我的斯堪的纳维亚角色 mWebView loadUrl file android asset om html 如果尝试这
  • Java - 从列表/数组中的每个对象获取单个属性的最简单方法?

    假设我有一个 person 对象 其属性如下name hair color and eye color 我有以下数组Person people包含 person 对象的实例 我知道我可以得到name一个人的财产Person对象与 creat
  • 如何在一行中将正则表达式匹配的结果分配给新变量?

    我想在一行中匹配并分配给一个变量 my abspath var ftp path to file txt abspath var ftp my relpath 1 我确信这一定很容易 my relpath abspath m var ftp
  • 使用 Bash 逐行读取并保留空格

    当我使用 cat test file 时 它会显示 1 2 3 4 当我使用 Bash 文件时 cat test file while read data do echo data done 它将显示 1 2 3 4 如何才能使结果与原始测
  • SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 和 FLAG_TRANSLUCENT_STATUS 已弃用

    此代码在 API 30 中已弃用 知道如何更新它吗 private fun setSystemBarLight act Activity if Build VERSION SDK INT gt Build VERSION CODES M v
  • 基于自定义线性渐变的UILabel文本颜色

    所以我想根据 Photoshop 中制作的渐变设置 UILabel 的文本颜色 我有渐变的 rgb 值 211 119 95 和 199 86 56 这可能吗 我该怎么做 如果您想以 iOS 6 为目标 使用 UIColor 类别的另一种方
  • 使用 REST 发布项目列表

    当我有一个 长 项目列表想要发布到服务器时 我正在寻找如何序列化数据的约定 例如 如果我有一个资源 users我想向它发布一个新的字段 我会对新用户的字段进行 http 编码 并将其放入请求正文中 如下所示 name foo age 20
  • 有新的/更新的斜纹布吗?

    我一直在尝试学习 Python 上的 Twill 脚本 并且正在使用Python 3 4 和 Twill 1 8 0 在这里阅读了一些帖子 我发现学习很有趣 但是 我在安装 Twill 时遇到了问题 我才知道PRINT在Python中现在是
  • JavaScript/JQuery 与 SerialPort/COM1 通信

    是否有可能强制进行任何通信 例如Javascript JQuery 到任何串行端口 谷歌无法回答这个问题 但无论如何它应该是可能的 在我的情况下env是firefox 非常欢迎想法 知识 请用胶带 我觉得有可能 查看 jUART 用于通过
  • 如何抑制单个 SQL 语句的列标题输出?

    我正在批量执行一些 SQL 语句 使用mysql命令行二进制 我希望我的几个 SELECT 语句之一不打印列标题 而只打印所选记录 这可能吗 使用以下命令调用 mysql N 别名为 N is skip column names 选项 my
  • ARM 上的 gdb 只报告回溯中的问号

    我正在尝试使用 ARM 上的 gdbserver 调试软件以获取崩溃的回溯 不幸的是我只得到问号 我到处都读到这个问题只是与缺少符号有关 但符号并没有从我的库中删除 如果我尝试使用 file 命令在客户端中加载符号 我会得到 reading
  • 当作为参数传递时,属性引用 (::test) 是否相当于访问属性 ({ test }) 的函数,例如`() -> 字符串`?

    我开始想知道是否通过访问属性 test相当于调用 test 或者它是否是使用反射的间接调用 当我看到以下内容时 我想到了这个问题 如何将属性 getter 作为函数类型传递给另一个函数 虽然两者 test and test 工作时 IDE