当前位置: 首页 > web >正文

Kotlin JVM 注解详解

前言

Kotlin 作为一门现代 JVM 语言,提供了出色的 Java 互操作性。为了更好地支持与 Java 代码的交互,Kotlin 提供了一系列 JVM 相关注解。这些注解不仅能帮助我们控制 Kotlin 代码编译成 Java 字节码的行为,还能让我们的 Kotlin 代码更好地被 Java 代码调用。虽然在日常开发中我们最常用的是 @JvmOverloads、@JvmStatic、@JvmName 和 @JvmField 这几个注解,但 Kotlin 其实还提供了更多强大的 JVM 注解。本文系统地整理下这些注解的作用、使用场景和具体示例,便于开发。
ps:以下整理基于kotlin-stdlib-1.7.10.jar!\kotlin\jvm\JvmInline.class

目录

  • @JvmOverloads
  • @JvmStatic
  • @JvmName
  • @JvmMultifileClass
  • @JvmPackageName
  • @JvmSynthetic
  • @Throws
  • @JvmField
  • @JvmSuppressWildcards
  • @JvmWildcard
  • @JvmInline
  • @JvmRecord

@JvmOverloads

作用

为带有默认参数值的函数生成重载方法。

使用场景

当 Kotlin 函数需要被 Java 代码调用时,特别是函数包含默认参数值的情况。

示例

@JvmOverloads
fun greet(name: String, greeting: String = "Hello") {println("$greeting, $name!")
}

编译后的 Java 代码

void greet(String name) {greet(name, "Hello");
}void greet(String name, String greeting) {System.out.println(greeting + ", " + name + "!");
}

@JvmStatic

作用

生成静态方法或静态属性访问器。

使用场景

在 companion object 中定义需要作为静态成员的方法或属性。

示例

class MyClass {companion object {@JvmStaticfun staticMethod() { }@JvmStaticvar staticProperty: String = ""}
}

@JvmName

作用

指定生成的 Java 类或方法的名称。

使用场景

  • 解决签名冲突
  • 自定义生成的 Java 代码名称
  • 改善 Java 代码的可读性

示例

@JvmName("filterString")
fun filter(list: List<String>) { }@JvmName("filterInt")
fun filter(list: List<Int>) { }

@JvmMultifileClass

作用

指示编译器生成多文件类,将多个文件中的顶级函数和属性合并到一个类中。

使用场景

需要将分散在多个文件中的相关功能组织在一起时。

示例

// File1.kt
@JvmName("Utils")
@JvmMultifileClass
fun function1() { }// File2.kt
@JvmName("Utils")
@JvmMultifileClass
fun function2() { }

@JvmPackageName

作用

更改生成的 .class 文件的 JVM 包名。

使用场景

需要自定义生成的 Java 代码的包名时。

注意

  • 内部注解,不推荐直接使用
  • 自 Kotlin 1.2 版本引入

@JvmSynthetic

作用

在 Java 字节码中设置 ACC_SYNTHETIC 标志,使目标对 Java 代码不可见。

使用场景

需要隐藏 Kotlin 特定的目标,使其对 Java 代码不可见,但保持对 Kotlin 代码可见。

示例

@JvmSynthetic
fun internalFunction() { }

@Throws

作用

指定函数编译为 JVM 方法时应声明的异常。

使用场景

需要从 Kotlin 代码中抛出 Java 检查异常时。

示例

@Throws(IOException::class)
fun readFile() { }

编译后的 Java 代码

void readFile() throws IOException { }

@JvmField

作用

指示编译器不要为属性生成 getter/setter,而是将其作为字段暴露。

使用场景

需要将 Kotlin 属性作为 Java 字段使用时。

示例

class MyClass {@JvmFieldvar field: String = ""
}

@JvmSuppressWildcards

作用

控制是否生成通配符。

使用场景

需要控制泛型类型参数的 Java 表示时。

示例

@JvmSuppressWildcards
fun process(list: List<String>) { }

@JvmWildcard

作用

为带声明点变异的类型参数生成通配符。

使用场景

需要控制泛型类型参数的 Java 表示时。

示例

fun process(@JvmWildcard list: List<String>) { }

@JvmInline

作用

指定值类为内联类。

使用场景

创建零开销的类型安全包装器。

示例

@JvmInline
value class Password(val value: String)

特点

  • 只能有一个主构造函数参数
  • 参数必须是不可变的(val)
  • 不能有 backing field
  • 不能有 init 块
  • 不能有 lateinit 属性

@JvmRecord

作用

指示编译器将类标记为记录类。

使用场景

创建不可变的数据类。

示例

@JvmRecord
data class Person(val name: String, val age: Int)

特点

  • 自 Kotlin 1.5 版本引入
  • 生成 toString、equals、hashCode 方法
  • 适用于不可变数据模型

最佳实践

  1. 选择合适的注解

    • 根据具体需求选择合适的注解
    • 考虑 Java 互操作性的需求
    • 注意注解的版本兼容性
  2. 性能考虑

    • 使用 @JvmInline 减少运行时开销
    • 合理使用 @JvmField 避免不必要的 getter/setter
    • 注意 @JvmStatic 的使用场景
  3. 代码可维护性

    • 使用 @JvmName 提高代码可读性
    • 使用 @Throws 明确异常处理
    • 使用 @JvmSynthetic 控制 API 可见性
  4. 版本兼容性

    • 注意注解的引入版本
    • 考虑向后兼容性
    • 关注 Kotlin 版本更新
http://www.xdnf.cn/news/10088.html

相关文章:

  • MySQL之数据库的内嵌函数和联合查询
  • Dify理论+部署+实战
  • 利用计算机模拟和玉米壳废料开发新型抗病毒药物合成方法
  • 详解Seata的核心组件TC、TM、RM
  • YOLOv8分割onnx实战及tensorRT部署
  • 黑森林实验室 FLUX.1Kontext:革新图像修改的 AI 力量
  • React 事件处理与合成事件机制揭秘
  • 计算机视觉入门:OpenCV与YOLO目标检测
  • 优化版本,增加3D 视觉 查看前面的记录
  • MySQL 的 super_read_only 和 read_only 参数
  • 板凳-------Mysql cookbook学习 (九)
  • MQTT的Thingsboards的使用
  • WebFuture:设置不自动删除操作日志
  • Celery简介
  • 全面解析:npm 命令、package.json 结构与 Vite 详解
  • 基于LBS的上门代厨APP开发全流程解析
  • 鸿蒙OSUniApp复杂表单与动态验证实践:打造高效的移动端表单解决方案#三方框架 #Uniapp
  • 特伦斯 S75 电钢琴:奏响极致音乐体验的华丽乐章
  • 大话软工笔记—分离之业务与管理
  • Spring Advisor增强规则实现原理介绍
  • 测试工程师学LangChain之promptTemplate 实战笔记
  • 数据库概念
  • 【论文解读】CVPR2023 PoseFormerV2:3D人体姿态估计(附论文地址)
  • 95套HTML高端大数据可视化大屏源码分享
  • 简单配置RHEL9.X
  • 换ip是换网络的意思吗?怎么换ip地址
  • MySql(八)
  • 当 Redis 作为缓存使用时,如何保证缓存数据与数据库(或其他服务的数据源)之间的一致性?
  • 历年中南大学计算机保研上机真题
  • 开发一款IIS自动检测修复工具