当一名 Java 开发者第一次听说 Kotlin,反应通常是以下两种之一。

第一种:"哦,有意思——我应该去了解一下。"

第二种:"有什么必要?Java 能用。工资照发。挺好的。"

Java vs Kotlin:诚实的比较 - 1

两种反应都可以理解。一个人在 Java 上花了多年心血,对它了如指掌,不想从头开始——这完全合理。

但还有第三种反应,没人提:我们 CTO 说下个季度就要迁移到这个语言了。

针对这三种情况——让我们诚实地看看这件事。没有宣战,没有狂热的布道。

Kotlin 从哪里来——以及 Oracle 与此有何关系

Java 出现于 1995 年。三十年——庞大的生态系统,Spring、Hibernate、Maven、Gradle,数以百万计的开发者,堆积如山的文档。这些不会消失。它活着,在发展,状态很好。

Kotlin 于 2016 年发布。JetBrains 为自己的需求创造了它——在开发 IntelliJ IDEA 的过程中被 boilerplate 搞得精疲力竭。关键决策:Kotlin 编译成与 Java 相同的 JVM 字节码。两者可以在同一个项目中协同工作。没有战争——只是不同的工具。

2017 年,Google 宣布 Kotlin 为 Android 的官方语言。

官方理由——开发者有需求,语言更方便。没错。

但有个背景值得了解。

从 2010 年开始,Google 与 Oracle 就 Android 中 Java API 的使用问题打起了官司。Oracle 索赔 88 亿美元——这个数字让 Google 也坐立不安。案子一直打到美国最高法院,直到 2021 年才以 Google 胜诉收场。十一年的法律不确定性。

JetBrains 的 Kotlin 是开源的,没有许可证风险。Google 从未官方承认这一决策与诉讼有关。但俗话说——相关不等于因果,直到它确实是因果的时候。

积极的一面:竞争推动了 Oracle 更主动地发展 Java。近几个版本里的 Records、sealed classes、pattern matching——部分原因就是要跟上 Kotlin 的步伐。不管 Oracle 愿不愿意,所有 JVM 开发者都从中获益。

语法:实战对比

同一个任务——从用户列表中筛选出 18 岁及以上的人。

// Java
List<User> adults = users.stream()
    .filter(u -> u.getAge() >= 18)
    .collect(Collectors.toList());

// Kotlin
val adults = users.filter { it.age >= 18 }

四行对一行。在大多数日常任务里,Kotlin 明显更简洁。

公平地说:Java 里所有东西都是显式的。读代码就知道发生了什么。Kotlin 里某些语法结构需要时间去适应。对初学者来说,Java 在这方面确实更透明。

但如果你在 Java 里浸泡了好几年,写 Collectors.toList() 靠肌肉记忆——也许那已经不是"显式"了,只是习惯。

Null-safety:最大的区别

Tony Hoare 在 1965 年发明了 null,后来公开称之为自己"价值十亿美元的错误"。罕见的作者亲口承认 bug 的案例。NullPointerException 从那以后给行业造成的损失远不止这个数——但谁在算呢。

// Java
String name = null;    // 编译器沉默
name.length();         // 运行时 NPE。通常是周五晚上。
                       // 有时候是在客户面前做现场演示的时候。

// Kotlin
var name: String = null   // 编译错误。立刻。在运行前。

var name: String? = null  // 明确声明可为 null — 现在没问题
name?.length              // 如果是 null — 返回 null,不会崩
name?.length ?: 0         // 如果是 null — 返回 0

Java 8 引入了 Optional 作为部分解决方案。有帮助,但不是到处都用——NPE 照样会出现。

在 Kotlin 里,null-safety 内置于类型系统。编译器不会放行可能触发 NPE 的代码,除非你明确允许。就像一个严格的 code reviewer——但没有"你这里检查 null 了吗?"这样的评论。

Boilerplate:data class 对比 POJO

一个简单的数据模型——有三个字段的用户。

// Java
public class User {
    private final String name;
    private final int age;
    private final String email;

    public User(String name, int age, String email) {
        this.name = name; this.age = age; this.email = email;
    }

    public String getName() { return name; }
    public int getAge() { return age; }
    public String getEmail() { return email; }

    @Override public boolean equals(Object o) { ... }
    @Override public int hashCode() { ... }
    @Override public String toString() { ... }
}

40 到 50 行。可以用 Lombok——但那要加依赖、配置 IDE,然后团队里总有人说"我这 Lombok 跑不起来"。

// Kotlin
data class User(val name: String, val age: Int, val email: String)

一行。编译器生成 equals()hashCode()toString()——以及 copy()

val weiwei = User("伟伟", 30, "weiwei@example.com")
val olderWeiwei = weiwei.copy(age = 31)  // 修改一个字段的副本

copy()——Java 开箱即用里没有的东西。为什么没有——好问题,Java 还没给出答案。

协程 vs 线程

Java 里的异步工作靠 ThreadExecutorServiceCompletableFuture。很强大。但代码很快就变成一条链,连写它的人一个月后都看不懂。

// Java
CompletableFuture.supplyAsync(() -> fetchUser(id))
    .thenApply(user -> processUser(user))
    .thenAccept(result -> sendResult(result))
    .exceptionally(e -> { handleError(e); return null; });

// Kotlin
suspend fun loadAndProcess(id: Int) {
    val user = fetchUser(id)
    val result = processUser(user)
    sendResult(result)
}

Kotlin 的代码读起来像普通的同步逻辑——从上到下,没有嵌套。但它依然是异步运行的,不阻塞任何线程。

重要说明:协程不是线程的替代品。它们最适合 I/O 密集型任务——用少量真实线程处理大量轻量级操作。对于 CPU 密集型的重计算,还是需要线程。协程在这方面帮不上忙。

互操作性——常被忽视的论点

Kotlin 和 Java 可以在同一个项目里同时工作。

Java 文件和 Kotlin 文件并排放置,互相调用方法,编译进同一个 JAR,使用同一套库。

这意味着:不是全部或全无。你可以从新模块开始用 Kotlin,不用动已有的代码。大多数团队就是这么做的——逐步推进,不搞英雄主义,不熬夜赶工。

Java 真正胜出的地方

文档和技术社区。Java 的资料积累了几十年。任何问题——技术论坛上早有一百个答案,其中一个是对的。与 Kotlin 的差距在缩小,但还存在。

遗留项目。一个用 Java 8 跑了 15 年、运行正常的系统——别动它。没有收益,只有风险。

企业环境。在大型组织里,技术栈的变化缓慢而痛苦。Java 对所有人来说都是熟悉的:团队、审计人员、安全部门。以及一年后加入然后问"我们为什么用 Kotlin?"的新同事。

Kotlin 真正胜出的地方

Android。案子结了。Google 官方推荐 Kotlin,所有新 API 都是为它写的,Jetpack Compose 也只支持 Kotlin。2026 年用 Java 开始一个新的 Android 项目,会让同事产生和骑马上班一样的反应。

新的后端服务。更少的代码、内置的 null-safety、协程——对新项目来说是个明智的选择。

Kotlin Multiplatform。用同一套代码库共享 iOS、Android 和 Web 的业务逻辑。Netflix、Philips 以及其他大公司已经在用了。

真的需要二选一吗?

不。

这不是"Java 还是 Kotlin"。这是"只用 Java,还是 Java 加上 Kotlin"。

Java 会留下——它的生态系统太庞大了,没有人会为了一门新语言去重写能用的代码。Kotlin 在增长——尤其是在移动端和新的后端项目里。

两者都懂,意味着更多的门会向你打开。而不会失去你已有的任何东西。

对于 Java 开发者来说,迁移需要几周。同一套 JVM,同样的逻辑。唯一需要做的就是开始。

如果你想认真学 Kotlin——我们有课程。62 个关卡,1100 多道题,3 个项目可加入作品集。第一关免费。

codegym.cc/zh/courses/kotlin

继续阅读