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…) 时运行。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…

基于 Spring Boot 策略模式的短信服务提供商动态切换实现

一、整体设计思路 为了实现在短信服务提供商变更时,不修改现有代码就能无缝切换到新服务实现,可采用策略模式结合依赖注入以及配置中心化管理的方式来设计软件系统。 二、 具体实现步骤 1. 定义统一接口(以短信服务为例,接口命名为 SmsService) 创建一个抽象的接口,用…

解决SQL Server SQL语句性能问题(9)——SQL语句改写(1)

9.4. SQL语句改写 目前主流关系库的高版本中,特别是作为主流商业关系库的SQL Server来讲,大部分场景中,同一语义和结果集的SQL语句,其不同写法并不会影响CBO为SQL语句生成和选择最合适、最高效的查询计划。但少数情况下,不同写法的同一语义和结果集的SQL语句,CBO也许会为…

设计模式复习小结

1.容易忘得设计原则 接口隔离&#xff1a;指接口中的功能太杂则可以拆分一下。防止实现类实现了接口后自动依赖了一些不需要的功能。不同功能拆分成不同的接口。 里氏代换&#xff1a;强调父类能出现的地方&#xff0c;子类一定能正常跑。 迪米特法则&#xff1a;又称最少知…

昇腾CANN集合通信技术解读——细粒度分级流水算法

随着AI技术的演进&#xff0c;模型的计算复杂度和参数量呈现几何级数增长&#xff0c;这使得传统单机单卡部署在算力供给与显存容量方面显得力不从心&#xff0c;从而直接推动了分布式训练/推理技术的快速发展。今年年初爆火的DeepSeek在训练及推理Prefill阶段采用了分级流水Al…

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…

React 进阶特性

1. ref ref 是 React 提供的一种机制,用于访问和操作 DOM 元素或 React 组件的实例。它可以用于获取某个 DOM 元素的引用,从而执行一些需要直接操作 DOM 的任务,例如手动设置焦点、选择文本或触发动画。 1.1. 使用 ref 的步骤 1. 创建一个 ref:使用 React.createRef 或 …

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…

【大厂机试题解法笔记】报文响应时间

题目 IGMP 协议中&#xff0c;有一个字段称作最大响应时间 (Max Response Time) &#xff0c;HOST收到查询报文&#xff0c;解折出 MaxResponseTime 字段后&#xff0c;需要在 (0&#xff0c;MaxResponseTime] 时间 (s) 内选取随机时间回应一个响应报文&#xff0c;如果在随机…

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…

Python爬虫实战:研究demiurge框架相关技术

1. 引言 在当今数字化时代,互联网上蕴含着海量的有价值信息。爬虫技术作为获取这些信息的重要手段,被广泛应用于学术研究、商业分析、舆情监测等多个领域。然而,构建一个高效、稳定且可维护的爬虫系统面临诸多挑战,如网页结构复杂多变、反爬机制日益严格、数据处理流程繁琐…

Jenkins | Jenkins构建成功服务进程关闭问题

Jenkins构建成功服务进程关闭问题 1. 原因2. 解决 1. 原因 Jenkins 默认会在构建结束时终止所有由构建任务启动的子进程&#xff0c;即使使用了nohup或后台运行符号&。 2. 解决 在启动脚本中加上 BULID_IDdontkillme #--------------解决jenkins 自动关闭进程问题-----…

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…

猜字符位置游戏-position gasses

import java.util.*;public class Main {/*字符猜位置游戏;每次提交只能被告知答对几个位置;根据提示答对的位置数推测出每个字符对应的正确位置;*/public static void main(String[] args) {char startChar A;int gameLength 8;List<String> ballList new ArrayList&…

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…

Towards Open World Object Detection概述(论文)

论文&#xff1a;https://arxiv.org/abs/2103.02603 代码&#xff1a;https://github.com/JosephKJ/OWOD Towards Open World Object Detection 迈向开放世界目标检测 Abstract 摘要 Humans have a natural instinct to identify unknown object instances in their environ…

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…