Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hl=zh-cn
一、Java(供 Kotlin 使用)
1、不得使用硬关键字
不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识符。
-
硬关键字
as、as?、break、class、continue、do、else、 false、for、fun、if、in、!in、interface、is、!is、null、object、package、super、this、throw、true、typealias、typeof、val、var、when、while。 -
软关键字、修饰符关键字和特殊标识符
https://kotlinlang.org/docs/keyword-reference.html#hard-keywords
2、避免使用 Any 的扩展函数或属性的名称
3、可为 null 性注释
- 公共 API 中的每个非基础参数类型、返回类型和字段类型都应 具有可为 null 性注解。
- 未加注解的类型会被解释为 “平台”类型,这些类型是否可为 null 性不明确。
4、Lambda 参数位于最后
- 符合 SAM 转换条件的参数类型应位于最后。例如,RxJava 2 的 Flowable.create() 方法签名定义为:
public static <T> Flowable<T> create(FlowableOnSubscribe<T> source,BackpressureStrategy mode) { /* … */ }// 在 kotlin 中调用时显示为Flowable.create({ /* … */ }, BackpressureStrategy.LATEST)
- 如果方法签名中的参数颠倒顺序,则函数会调用 可以使用尾随 lambda 语法:
public static <T> Flowable<T> create(BackpressureStrategy mode,FlowableOnSubscribe<T> source) { /* … */ }// 在 kotlin 中调用时显示为Flowable.create(BackpressureStrategy.LATEST) { /* … */ }
5、属性前缀
- 对于在 Kotlin 中要表示为属性的方法,需要严格的**“bean”样式** 前缀。
- 访问器方法需要 get 前缀;对于布尔值返回方法,则为 is 前缀。
- 更改器方法需要 set 前缀。
- 如果希望方法作为属性公开,请不要使用非标准前缀,例如 has、set 或无 get 前缀的访问器。带有非标准前缀的方法 也可作为函数进行调用,具体取决于 方法的行为。
public final class User {public String getName() { /* … */ }public void setName(String name) { /* … */ }public boolean isActive() { /* … */ }public void setActive(boolean active) { /* … */ }}// 对应的 kotlin 代码val name = user.name // Invokes user.getName()val active = user.isActive // Invokes user.isActive()user.name = "Bob" // Invokes user.setName(String)user.isActive = true // Invokes user.setActive(boolean)
6、运算符过载
- 允许特殊调用点语法。
public final class IntBox {private final int value;public IntBox(int value) {this.value = value;}public IntBox plus(IntBox other) {return new IntBox(value + other.value);}}// kotlin 代码val one = IntBox(1)val two = IntBox(2)val three = one + two // Invokes one.plus(two)
二、Kotlin(供 Java 使用)
1、文件名
- 如果文件包含顶级函数或属性,请始终为其添加注解 使用 @file:JvmName(“Foo”) 提供一个好记的名称。
- 默认情况下,MyClass.kt 文件中的顶级成员最终将位于名为 MyClassKt 文件中,该名字没有吸引力,并且会泄露作为实现的语言 。
- 建议您添加“@file:JvmMultifileClass”,它是 Kotlin 中的一个注解,用于支持将一个 Kotlin 文件拆分成多个部分,这些部分在 Java 中被视为同一个类的一部分。
- 使用 @file:JvmMultifileClass 注解时,通常会结合 @file:JvmName 注解来指定生成的 Java 类的名称。这样,多个 Kotlin 文件可以合并成一个 Java 类,而不会出现命名冲突。
2、Lambda 参数
- 使用 Java 定义的单一方法接口 (SAM) 可以用 Kotlin 语言实现,也可以使用 lambda 语法的 Java 语言以惯用方式内嵌实现。
(1)首选定义
- 要在 Java 中使用的高阶函数,不应接受会返回 Unit 的函数类型,而建议使用功能 (SAM) 接口。
- 即使函数类型不会返回 Unit,仍建议您将其设为命名接口,以便调用方使用命名类来实现它,而非只使用 lambda(在 Kotlin 和 Java 中)。
- 在定义预期用作 lambda 的接口时,优先考虑使用功能 (SAM) 接口,而不是常规接口 ,用以支持 Kotlin 中的惯用用法。
// 高阶函数,函数类型为 (String) -> Unitfun sayHi(greeter: (String) -> Unit)// 建议使用 SAM 接口fun interface GreeterCallback {fun greetName(String name)}fun sayHi(greeter: GreeterCallback) = /* … */// kotlin 中调用sayHi { println("Hello, $it!") }// java 中调用sayHi(name -> System.out.println("Hello, " + name + "!"));// 实现接口的命名类class MyGreeterCallback : GreeterCallback {override fun greetName(name: String) {println("Hello, $name!");}}
(2)避免使用会返回 Unit 的函数类型
- 返回 Unit 的函数类型要求 Java 调用方返回 Unit.INSTANCE
// kotlinfun sayHi(greeter: (String) -> Unit) = /* … */// 对应的 java 调用sayHi(name -> {System.out.println("Hello, " + name + "!");return Unit.INSTANCE;});
(3)如果接口实现持有状态,请避免使用功能接口
- 当接口实现需要持有状态时,使用 lambda 语法是没有意义的。Comparable 是一个典型的例子,因为它需要比较 this 和 other,而 lambda 表达式没有 this。不使用 fun 修饰接口会迫使调用者使用 object : … 语法,这允许实现中持有状态,同时也为调用者提供了一个提示。
- 不使用 fun 修饰的接口无法在 Kotlin 中使用 lambda 语法。
// No "fun" prefix.interface Counter {fun increment()}runCounter(object : Counter {private var increments = 0 // State override fun increment() {increments++}})
3、避免使用 Nothing 类属
- 泛型参数为 Nothing 的类型会作为原始类型提供给 Java。原始 类型在 Java 中很少使用,应予以避免使用。
4、防御性复制
- 在从公共API返回共享的或无主的只读集合时,应将其包装在一个不可修改的容器中,或者执行防御性拷贝。尽管Kotlin强制执行了它们的只读属性,但Java端并没有这样的强制性。如果没有包装器或防御性拷贝,返回一个长期存在的集合引用可能会破坏不变性。
5、伴生函数
- 伴生对象中的公共函数必须带有 @JvmStatic 注解使其公开为静态方法,如果没有该注解,这些函数在 Java 中只能作为实例方法使用。
// 不正确,没有 @JvmStatic 注解class KotlinClass {companion object {fun doWork() {/* … */}}}// 在 java 中调用public final class JavaClass {public static void main(String... args) {KotlinClass.Companion.doWork();}}// 正确,添加 @JvmStatic 注解class KotlinClass {companion object {@JvmStatic fun doWork() {/* … */}}}// 在 java 中调用public final class JavaClass {public static void main(String... args) {KotlinClass.doWork();}}
6、伴生常量
- 作为 companion object 中的有效常量的公共非 const 属性必须带有 @JvmField 注解,java 调用时才能作为静态字段提供。
- 如果没有该注解,这些属性只能作为静态Companion字段上奇怪命名的实例“getter”方法使用。
- 而使用@JvmStatic替代@JvmField,则会将这些奇怪命名的“getter”方法移动到类的静态方法中,但这仍然是不正确的。
// 1、不正确,没有注解class KotlinClass {companion object {const val INTEGER_ONE = 1val BIG_INTEGER_ONE = BigInteger.ONE}}// java 中调用public final class JavaClass {public static void main(String... args) {System.out.println(KotlinClass.INTEGER_ONE);System.out.println(KotlinClass.Companion.getBIG_INTEGER_ONE());}}// 2、不正确:@JvmStatic 注释class KotlinClass {companion object {const val INTEGER_ONE = 1@JvmStatic val BIG_INTEGER_ONE = BigInteger.ONE}}// java 中调用public final class JavaClass {public static void main(String... args) {System.out.println(KotlinClass.INTEGER_ONE);System.out.println(KotlinClass.getBIG_INTEGER_ONE());}}//3、正确:@JvmField 注释class KotlinClass {companion object {const val INTEGER_ONE = 1@JvmField val BIG_INTEGER_ONE = BigInteger.ONE}}// java 中调用public final class JavaClass {public static void main(String... args) {System.out.println(KotlinClass.INTEGER_ONE);System.out.println(KotlinClass.BIG_INTEGER_ONE);}}
7、符合语言习惯的命名
- Kotlin 的调用规范与 Java 不同,这可能会改变您为函数命名的方式。使用 @JvmName 设计符合语言习惯的名称 或匹配各自的标准库 命名。
- 扩展函数和扩展属性最常出现这种情况 因为接收器类型的位置不同。
sealed class Optional<T : Any>data class Some<T : Any>(val value: T): Optional<T>()object None : Optional<Nothing>()@JvmName("ofNullable")fun <T> T?.asOptional() = if (this == null) None else Some(this)// FROM KOTLIN:fun main(vararg args: String) {val nullableString: String? = "foo"val optionalString = nullableString.asOptional()}// FROM JAVA:public static void main(String... args) {String nullableString = "Foo";Optional<String> optionalString =Optionals.ofNullable(nullableString);}
8、默认值的函数过载
- 参数具有默认值的函数必须使用 @JvmOverloads。如果没有此注解,则无法使用任何默认值来调用函数。
- 在使用@JvmOverloads时,要检查生成的方法,确保每个方法都合理。如果它们不合理,请执行以下一种或两种重构操作,直到满意为止:
- 调整参数顺序,将带有默认值的参数放在最后。
- 将默认值移入手动实现的函数重载中。
// 不正确:没有 @JvmOverloadsclass Greeting {fun sayHello(prefix: String = "Mr.", name: String) {println("Hello, $prefix $name")}}// java 调用public class JavaClass {public static void main(String... args) {Greeting greeting = new Greeting();greeting.sayHello("Mr.", "Bob");}}// 正确:@JvmOverloads 注释class Greeting {@JvmOverloadsfun sayHello(prefix: String = "Mr.", name: String) {println("Hello, $prefix $name")}}// java 调用public class JavaClass {public static void main(String... args) {Greeting greeting = new Greeting();greeting.sayHello("Bob");}}
三、Lint 检查
- 在 Android 开发中,Lint 检查 是一种静态代码分析工具,用于检查代码中的潜在问题,帮助开发者在编译之前发现并修复代码中的错误、性能问题、安全问题、可维护性问题等。
1、环境要求
- Android Studio 版本:3.2 Canary 10 或更高版本
- Android Gradle 插件版本:3.2 或更高版本
2、支持的检查
- 支持的检查包括:
- 未知 Null 性
- 属性访问
- 不得使用 Kotlin 硬关键字
- Lambda 参数位于最后
3、Android Studio 中启用检查
- Android Studio 中要启用这些检查,请依次点击 File > Settings >Editor >Inspections,在 “Android Lint: Interoperability” 下选中您要启用的规则。
- 选中要启用的规则后,新的检查将 在运行代码检查 (Code > Inspect Code…) 时运行。
相关文章:

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...