206-Kotlin 与 Java 互操作
06 Kotlin 与 Java 互操作
这一章解决“在 Java/Kotlin 混合工程里安全互调”。绝大多数 Android 项目都是混合的:依赖库是 Java,老代码是 Java,新代码是 Kotlin。互操作最危险的就是平台类型带来的空陷阱。
1. 为什么要关心互操作
- Android Framework(
Activity、View、Context等)本身是 Java。 - 大量三方库(OkHttp 之外的旧库、厂商 SDK)是 Java。
- 老项目迁移过程中,Java 和 Kotlin 长期共存。
Kotlin 设计目标之一就是和 Java 100% 互操作,但“能调通”不等于“没有坑”。最大的坑是空安全在边界处会“漏”。
2. 平台类型与空陷阱(核心)
Java 类型没有可空信息。Kotlin 调到 Java 返回值时,给它一个平台类型,记作T!,意思是“可空性未知”。
// Java: public String getName() { ... } 可能返回 nullvalname=javaUser.name// 类型是 String!(平台类型)vallen=name.length// 编译通过!但运行时若为 null 就 NPE平台类型的危险在于:Kotlin不强制你判空,于是 Java 的null会绕过空安全直接制造 NPE。这是 Kotlin 项目里 NPE 的两大来源之一(另一个是!!)。
应对原则:在 Java 边界处,显式声明可空性,逼自己处理。
valname:String?=javaUser.name// 显式声明可空vallen=name?.length?:0// 安全处理| 写法 | 结果 |
|---|---|
val n = javaUser.name(推断String!) | 不判空,运行时可能 NPE |
val n: String = javaUser.name | 若 Java 返回 null,赋值时立刻 NPE(至少崩在边界) |
val n: String? = javaUser.name | 安全,强制后续处理 |
3. 用空注解改善推断
如果 Java 代码(或它依赖的库)在方法/参数上加了空注解,Kotlin 会据此推断可空性,平台类型就消失了。
// Javapublic@NullableStringgetName(){...}publicvoidsetName(@NonNullStringname){...