Skip to content

Kotlin 相比 Java 的核心优势,天天在用但没系统梳理过——空安全、扩展函数、数据类、密封类,这几个特性解决了 Java 的哪些痛点、各自怎么用。这篇把这几个核心特性讲清楚。

一、空安全:干掉 NullPointerException

Java 最大的坑就是 NPE(空指针),Kotlin 用类型系统在编译期就把空指针挡在门外:

kotlin
var name: String = "BinMaker"   // 非空类型:不可能为 null
// name = null                   // ❌ 编译报错,直接不允许

var nick: String? = null        // 可空类型:用 ? 声明,可以为 null

对可空类型,必须显式处理空才能用,有三种手段:

kotlin
val nick: String? = null

// ① 安全调用 ?. :为 null 时整个表达式返回 null,不崩
val len = nick?.length          // 结果是 null,而不是抛 NPE

// ② Elvis 操作符 ?: :为 null 时给默认值
val len2 = nick?.length ?: 0    // null 就取 0

// ③ 非空断言 !! :我确定不为 null,为 null 就抛异常(谨慎用)
val len3 = nick!!.length        // 为 null 会抛 NPE,等于放弃 Kotlin 的保护

核心?.?: 是日常主力,!! 是"我确定不为空"时才用。空安全让 NPE 从"运行时爆炸"变成"编译期报错"。

二、扩展函数:给已有类加方法,不改原类

想给 String 加个方法,Java 得继承或写工具类,Kotlin 直接扩展

kotlin
// 给 String 加扩展函数:加个感叹号
fun String.addExclamation() = this + "!"

"hello".addExclamation()   // "hello!"

// 给集合加扩展:取第二个元素
fun <T> List<T>.secondOrNull() = if (size >= 2) this[1] else null
listOf(1, 2, 3).secondOrNull()   // 2

本质:扩展函数不修改原类,只是编译成静态方法(接收者作为第一个参数),但调用起来像原生方法一样顺。

三、数据类:一行搞定 Java 的样板代码

Java 写个"数据类"要手写 equals/hashCode/toString/getter,一大坨。Kotlin 一个 data 关键字全搞定:

kotlin
data class User(val name: String, val age: Int)
// 自动生成:equals、hashCode、toString、copy、componentN(解构)

val u = User("BinMaker", 18)
println(u)                    // User(name=BinMaker, age=18)
val u2 = u.copy(age = 20)     // 复制并改字段,原来不动
val (name, age) = u           // 解构声明

data class 是 Kotlin 最常用的特性之一——模型类、状态类基本都用它。

四、密封类:受限的类层级,配合 when 穷举

sealed class 限制子类只能定义在同一个文件里,配合 when 能穷举所有情况(编译器强制你覆盖全部):

kotlin
sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val msg: String) : Result()
    object Loading : Result()
}

fun handle(result: Result) = when (result) {
    is Result.Success -> "成功: ${result.data}"
    is Result.Error -> "失败: ${result.msg}"
    Result.Loading -> "加载中"
    // 不需要 else —— 编译器知道所有子类都覆盖了
}

好处:新增一个子类(比如 Timeout),when 会编译报错提醒你漏了处理——比 Java 的"到处写 else 兜底"安全得多。

小结

  • 空安全:? 声明可空,?. 安全调用、?: 默认值、!! 非空断言,NPE 从运行时变编译期
  • 扩展函数:给已有类加方法,不改原类
  • 数据类:data class 自动生成 equals/hashCode/toString/copy/解构
  • 密封类:限制子类 + when 穷举,新增子类编译器强制你处理

这几个特性是 Kotlin 的"门面",理解后就能写出更简洁安全的代码。想了解 Kotlin 的高阶函数和 let/apply 这些作用域函数,看《Kotlin 高阶函数与作用域函数》;想了解 Kotlin 的并发王牌,看《Kotlin 协程详解》。