如何使用反射更改 kotlin 私有 val?

2024-04-14

我可以使用反射访问私有 val 值,如下所示

fun main() {
    val mainClass = MainClass()
    val f = MainClass::class.memberProperties.find { it.name == "info" }
    f?.let {
        it.isAccessible = true
        val w = it.get(mainClass) as String
        println(w)
    }
}


class MainClass {
    private val info: String = "Hello"
}

但如果我想改变info,我该如何使用反射来做到这一点?


Answer

简而言之,在这种情况下您必须使用 Java 反射 API,具体操作方法如下:

fun main() {
    val mainClass = MainClass()
    val f = MainClass::class.java.getDeclaredField("info")
    f.isAccessible = true
    f.set(mainClass, "set from reflection")
    mainClass.printInfo() // Prints "set from reflection"
}

class MainClass {
    private val info: String = "Hello"
    fun printInfo() = println(info)
}

使用 Java 反射 API 的原因

无法使用 Kotlin 反射 API 执行此操作,因为不会为只读生成 setter 代码 (val) 财产。因此,要改变它,我们需要使用更底层的Java反射API。首先,我们使用Tools -> Kotlin -> 显示 Kotlin 字节码查看生成的字节码是什么样子的。然后我们看到这个:

// ================MainClass.class =================
// class version 50.0 (50)
// access flags 0x31
public final class MainClass {
  // access flags 0x12
  private final Ljava/lang/String; info = "Hello"
  // ...

info中的字段MainClassKotlin 类会导致编译器发出常规的 JVM 代码MainClassJava 类有一个final String info场地。因此,要更改它,我们可以使用 Java 反射 API,如上面的代码所示。

Kotlin 反射 API 尝试

如果该字段是private var您将能够像这样使用 Kotlin 反射 API:

f?.let {
    val mutableProp = it as KMutableProperty<*>
    it.isAccessible = true
    mutableProp.setter.call(mainClass, "set from Kotlin reflection")
    val w = it.get(mainClass) as String
    println(w)
}

但如果你尝试这样做private val你会得到以下异常

Exception in thread "main" java.lang.ClassCastException: class kotlin.reflect.jvm.internal.KProperty1Impl cannot be cast to class kotlin.reflect.KMutableProperty (kotlin.reflect.jvm.internal.KProperty1Impl and kotlin.reflect.KMutableProperty are in unnamed module of loader 'app')
    at MainKt.main(main.kt:107)
    at MainKt.main(main.kt)

因为没有生成 setter 代码val场,因此info属性将具有 Kotlin Reflection API 类型KProperty并不是KMutableProperty.

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

如何使用反射更改 kotlin 私有 val? 的相关文章

随机推荐

  • XSLT 在特定元素之间包裹节点

    我有以下 TEI 文件
  • PHP DomDocument HTML 操作

    我有以下 HTML div div Current Div div div 在 PHP 中使用 DomDocument 我尝试在 id 为 current 的 div 之前向 HTML 添加一个额外的 div div div New Div
  • 在电子应用程序中从主程序到渲染器发出自定义事件

    所以我知道这是有效的 因为我尝试过 但它没有在任何地方记录 所以我问是否可以使用这种做法 而不用担心它将来会停止工作 众所周知 Electron 和 Nodejs 会破坏一个东西 版本到另一个 这就是我所说的练习类型 main js app
  • Nokogiri 在 OS X 上安装失败

    关于此问题的帖子有很多 但是 Nokogiri 版本 1 6 x 1 7 x 或 1 8 x 无法在 OS X 上安装可能有多种原因 相关文章 OS X 10 6 安装 Nokogiri https stackoverflow com qu
  • 让 Visual Studio Code 将无扩展名文件语法高亮显示为 bash 脚本?

    我已经开始编写一些 bash 脚本来增强 git 使用视觉工作室代码 https code visualstudio com 我希望编辑器在执行此操作时使用语法突出显示 这些文件没有扩展名 否则 git 不会将它们作为附加命令 以下是此类脚
  • 启动请求重复得太快

    我正在编写 bash 脚本 但经常遇到这个问题 当我尝试start or stop我经常得到的服务 start request repeated too quickly 我怎么解决这个问题 例如 当我尝试重新启动 docker 或 open
  • 如何防止Python中的某些特定键“发送”输入

    我正在尝试使用Python 来代替AutoHotkey 我已经设置了 pynput 来监听按键 并且大部分内容都按照我的预期工作 但是 我有一个问题 如果我通过监听键盘并在按键上执行某些操作来 重新绑定 一个键 它仍然会发送原始命令 我不了
  • WinRT 中的 ICMP Ping - 可能吗? [复制]

    这个问题在这里已经有答案了 如何在 WinRT 现代 UI 应用程序中执行 ICMP ping 目前 WinRT 中未实现 Ping 请参阅相关问题here https stackoverflow com questions 1095234
  • 为什么我的汇编程序没有将 r1 设置为正确的值?

    我正在 LC3 机器上编写汇编程序 我的汇编程序是一个 LC3 程序 它将 R2 和 R3 相乘并将结果存储在 R1 中 这是我的源代码 带注释 Sets pc to this address at start of program ORI
  • 如何在文本中添加/插入 xml 节点

    我正在生成一个基于 XML 的开放文档格式 odt 的文本文档 但是在文本段落中添加制表符时遇到问题 当我在 Open Office 应用程序中创建它并保存文档时 该段落的内部 XML 表示形式为
  • 最小最大价格范围验证不适用于 jquery.validate.js

    我正在使用的表单验证https jqueryvalidation org https jqueryvalidation org 我已经通过 dependent 属性实现了自定义验证规则 以下是验证错误规则 如果未选择两个价格框 则不会显示错
  • 如果字符串是...然后用图像替换它?

    我有以下代码 对此有三种可能的字符串输出 food drink food Drink 我想用小图标替换这些字符串 例如代表 饮料 的玻璃杯 有没有一种简单的方法可以用 PHP 来做到这一点 Thanks 您可以通过数组映射值 items a
  • 鉴于其中一些变量可能不存在,如何保留变量列表?

    我有100个dta文件 我有一个我需要的变量列表keep并即时保存临时副本 某些变量可能存在于某个特定的环境中 也可能不存在dta 我需要 Stata 来保留 a 中存在的所有变量dta并忽略那些不存在的 下面的代码有错误的语法 但它可以作
  • div 内的左/右浮动按钮

    如何让按钮只浮动在div区域 这是我的 CSS 和 HTML 示例 test width 60 display inline overflow auto white space nowrap margin 0px auto div clas
  • 将自定义中心按钮添加到选项卡栏的最佳方法是什么?

    许多应用程序都有一个标准选项卡栏 中间有一个自定义按钮 可以执行一些特殊功能 一些例子可以在这里找到 http mobile patterns com custom tab navigation http mobile patterns c
  • Powershell Get-ChildItem 目录中的最新文件

    我们生成名称中带有日期的文件 下面是日期的通配符 我想获取最后一个文件 并且包含该文件的文件夹的标题中也有一个日期 仅月份 我正在使用 PowerShell 并安排它每天运行 这是到目前为止的脚本 LastFile DailyFile co
  • 使用项目资源(WPF)的图像源

    我添加了一堆图像作为项目资源 现在我想在我的 WPF 应用程序中使用图像控件来使用它们 如何将资源分配给图像控件的源 首先 在 Visual Studio 的属性窗口中将图像文件标记为 资源 然后您可以很容易地使用文件名引用资源
  • 多个 bitbucket 帐户的 ssh 配置 - 简单的示例,但出现“远程端意外挂断”

    假设我的 bitbucket 用户名是 jon 并且我有一些个人项目https bitbucket org jon 假设我加入了一个开发团队 该团队有一个名为 devteam 的 bitbucket 帐户 可以在以下位置找到该帐户 http
  • 一个月中的一周熊猫

    我试图每个月坚持一周 有些月份可能有四个星期 有些可能有五个星期 对于每个日期 我想知道它属于哪一周 我最感兴趣的是本月的最后一周 data pd DataFrame pd date range 1 1 2000 periods 100 f
  • 如何使用反射更改 kotlin 私有 val?

    我可以使用反射访问私有 val 值 如下所示 fun main val mainClass MainClass val f MainClass class memberProperties find it name info f let i