NullPointerException → Kotlin 空安全
老写法(Java --- NPE 高发代码)
scss
// 1. 链式调用中间为 null
String city = user.getAddress().getCity(); // address 可能是 null
// 2. Intent 取值没判空
String title = getIntent().getStringExtra("title");
int length = title.length(); // title 可能是 null
// 3. findViewById 在错误的 layout
TextView tv = findViewById(R.id.tv_not_exist);
tv.setText("hello"); // tv 是 null
问题在哪里
Java 的类型系统不区分"可以为 null"和"不能为 null",null 可以出现在任何地方。@Nullable / @NonNull 注解只是提示,不强制编译检查。线上 NPE 是最常见的崩溃原因。
新写法(Kotlin 空安全)
ini
// 1. 安全调用 --- 中间任意一环为 null,整个表达式返回 null
val city = user?.address?.city
// 2. Elvis 操作符 --- null 时给默认值
val title = intent.getStringExtra("title") ?: ""
val length = title.length
// 3. let --- 不为 null 时执行
user?.address?.city?.let { city ->
updateCityUI(city)
}
// 4. 强制非 null --- !!(尽量不用,确定不为 null 时才用)
val tv = findViewById<TextView>(R.id.tv_title)
tv!!.text = "hello"
一句话注意
把 Java 代码迁移到 Kotlin 后,NPE 几乎全部在编译期被消灭。Kotlin 的规则很简单:类型后面带 ? 的可以为 null,不带的不能为 null。Java 代码和 Kotlin 交互的地方需要特别注意------Java 返回的类型在 Kotlin 里是"平台类型",编译器不会强制检查 null,需要手动声明为可空类型。
老项目迁移期间,Java 和 Kotlin 混编阶段最容易在边界处出问题。建议在 Java 方法上统一加 @Nullable / @NonNull 注解,Kotlin 编译器会识别这些注解来做空检查。
Java Android 老项目迁移系列,持续更新中。