Kotlin语法笔记(28) -Kotlin 与 Java 混编

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
公网NAT网关,每月750个小时 15CU
简介: 本系列教程详细讲解了Kotlin语法,适合需要深入了解Kotlin的开发者。对于希望快速学习Kotlin的用户,推荐查看“简洁”系列教程。本文档重点介绍了Kotlin与Java混编的技巧,包括代码转换、类调用、ProGuard问题、Android library开发建议以及在Kotlin和Java之间互相调用的方法。

本系列学习教程笔记属于详细讲解Kotlin语法的教程,需要快速学习Kotlin语法的小伙伴可以查看“简洁” 系列的教程

快速入门请阅读如下简洁教程:
Kotlin学习教程(一)
Kotlin学习教程(二)
Kotlin学习教程(三)
Kotlin学习教程(四)
Kotlin学习教程(五)
Kotlin学习教程(六)
Kotlin学习教程(七)
Kotlin学习教程(八)
Kotlin学习教程(九)
Kotlin学习教程(十)

Kotlin教程笔记(28) -Kotlin 与 Java 混编

Kotlin 与 Java 混编
虽然 Kotlin 的开发很方便,但当你与他人协作时,总会碰到 Java 与 Kotlin 代码共存的代码项目。 本章就教你如何优雅的实现 Kotlin 与 Java 混合编程。

  1. 直接转换
    1.1 将 Java 转换为 Kotlin
    如果你之前使用 Java 语言而没有 Kotlin 开发经验,不用担心,Intellij IDEA 会帮你一键转换,将 Java 代码转换成 Kotlin 代码(但是反过来就不行了)。

在 Mac 上,系统默认的快捷键为control+shift+command+K,这个组合键实在有点反人类,建议你自定义一个你觉得舒服的快捷键。

快捷键可以通过你的编译器 keymap 中修改:command+, -> 搜索keymap -> 右侧搜索kotlin,可以查看到Convert Java File to Kotlin File项。

kotlin与java互操作

1.2 注意 Class 调用
在 Java 或 Android 开发中,经常会直接调用一个类的 Class 文件。但是当你用上文介绍的转换方法去转换 XXX.class这样的代码时,是无法直接转换的(也许未来会修复这个问题,但目前你扔需要手动修改)。在 M13 之前,Java 中的XXX.class对应 Kotlin 代码中的JavaClass,而 M13 之后写法已被改为XXX::class.java。

1.3 Android proguard 的坑
注:我们团队遇到过这样的一个坑,在 Android 开发的时候,如下代码会在混淆以后,发生异常

var str = some?.s?.d ?: ""
这段代码在正常debug模式编译运行完全正常,但是一旦执行混淆,就会发生所在函数被移除的现象。 但是如果改写为以下写法就能正常运行:

var str = some?.s?.d ?: String()
猜想应该是 proguard 不知道如何处理这段代码,无法识别出最后两个引号是一个String,最后直接将整个函数移除掉了。

同样的代码还有:

var list = some?.data?.list:mutableListof()
但是如下代码即使混淆后也是可以完全正常执行的

var s = some?.s ?: ""
var s = some.d ?: ""
var list = some?.data?.list:klist
var data = some?.data ?: return
1.4 开发 Android library 的建议
如果你是开发 Android library 程序,建议你不要使用 Kotlin 代码。因为作为 library,如果使用它的工程是纯 Java 完成的,引入后会额外增大 200k 左右大小,同时它有可能会造成某些情况下编译异常。

  1. 在 Kotlin 中调用 Java 代码
    2.1 返回 void 的方法
    如果一个 Java 方法返回 void,对应的在 Kotlin 代码中它将返回 Unit。关于 Unit,本书将在 第五章函数部分着重讲解。 现在你只需要知道在Java 中返回为 void 的函数,在 Kotlin 中可以省略这个返回类型。

2.2 与 Kotlin 关键字冲突的处理
Java 有 static 关键字,在 Kotlin 中没有这个关键字,你需要使用@JvmStatic替代这个关键字。 同样,在 Kotlin 中也有很多的关键字是 Java 中是没有的。例如 in,is,data等。如果 Java 中使用了这些关键字,需要加上反引号(`)转义来避免冲突。例如

// Java 代码中有个方法叫 is()
public void is(){
//...
}

// 转换为 Kotlin 代码需要加反引号转义
fun is() {
//...
}
3 在 Java 中调用 Kotlin 代码
3.1 static 方法
上文已经提到过,在 Kotlin 中没有 static关键字,那么如果在 Java 代码中想要通过类名调用一个 Kotlin 类的方法,你需要给这个方法加入@JvmStatic注解(这个注解只在 jvm 平台有用)。否则你必须通过对象调用这个方法。

StringUtils.isEmpty("hello");
StringUtils.INSTANCE.isEmpty2("hello");

object StringUtils {
@JvmStatic fun isEmpty(str: String): Boolean {
return "" == str
}

fun isEmpty2(str: String): Boolean {
    return "" == str
}

}
如果你阅读 Kotlin 代码,应该经常看到这样一种写法。

class StringUtils {
companion object {
fun isEmpty(str: String): Boolean {
return "" == str
}
}
}
companion object表示外部类的一个伴生对象,你可以把他理解为外部类自动创建了一个对象作为自己的field。 与上面的类似,Java 在调用时,可以这样写:StringUtils.Companion.isEmpty();(1.1以后可以省略中间的 Companion,写作 StringUtils.isEmpty())

关于伴生对象,我们将在下一章 类与对象 详细讲解。

3.2 包级别函数
与 Java 不同,Kotlin 允许函数独立存在,而不必依赖于某个类,这类函数我们称之为包级别函数(Package-Level Functions)。

为了兼容 Java,Kotlin 默认会将所有的包级别函数放在一个自动生成的叫ExampleKt的类中, 在 Java 中想要调用包级别函数时,需要通过这个类来调用。

当然,也是可以自定义的,你只需要通过注解@file:JvmName("Example")即可将当前文件中的所有包级别函数放到一个自动生成的名为 Example 的类中。

3.3 空安全性
在 Java 中,如果你调用的 kotlin 方法参数声明了非空类型,如果你在 Java 代码中传入一个空值,将在运行时抛出NullPointerException。其内部原因在于 Kotlin 为每个非空类型加了断言,如果传入空值则会立刻抛出异常。 同样,如果你使用 null 对象去调用一个 kotlin 方法,将会立刻抛出NullPointerException(就算是调用普通 java 方法也是一样会抛出 NullPointerException )

相关文章
|
2月前
|
存储 Java 开发者
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
本文详细介绍了 Java 中 `toString()` 方法的重写技巧及其重要
56 10
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
|
22天前
|
数据采集 前端开发 JavaScript
如何利用Java和Kotlin实现动态网页内容抓取
如何利用Java和Kotlin实现动态网页内容抓取
|
2月前
|
前端开发 JavaScript Java
Java构建工具-maven的复习笔记【适用于复习】
这篇文档由「潜意识Java」创作,主要介绍Maven的相关知识。内容涵盖Maven的基本概念、作用、项目导入步骤、依赖管理(包括依赖配置、代码示例、总结)、依赖传递、依赖范围以及依赖的生命周期等七个方面。作者擅长前端开发,秉持“得之坦然,失之淡然”的座右铭。期待您的点赞、关注和收藏,这将是作者持续创作的动力! [个人主页](https://blog.csdn.net/weixin_73355603?spm=1000.2115.3001.5343)
44 3
|
3月前
|
Java 编译器 Kotlin
Kotlin入门笔记1 - 数据类型
Kotlin入门笔记1 - 数据类型
92 15
|
3月前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
49 2
|
3月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
43 2
|
3月前
|
Java 数据库连接 编译器
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
Kotlin教程笔记(29) -Kotlin 兼容 Java 遇到的最大的“坑”
97 0
|
Java 编译器 API
【Kotlin 初学者】Java和Kotlin互操作
一、Kotlin调用Java 1.1 互操作性与可空性 1.2 类型映射 1.3 属性访问 二、Java调用Kotlin 2.1 @JvmName 2.2 @JvmField 2.3 @JvmStatic 2.4 @JvmOverloads 2.4.1 未使用@JvmOverloads注解 2.4.2 使用@JvmOverloads注解 2.5 @Throws 2.6 函数类型操作
290 0
【Kotlin 初学者】Java和Kotlin互操作
|
安全 Java 索引