Java vs Kotlin
一句话概括
| Java | Kotlin | |
|---|---|---|
| 诞生年份 | 1995 | 2011 |
| 主要设计目标 | 通用、跨平台、“Write Once, Run Anywhere” | 更安全、更简洁、与 Java 100% 互操作 |
| 主要维护方 | Oracle / OpenJDK 社区 | JetBrains / Kotlin 基金会 |
| 编译产物 | JVM 字节码(.class) |
JVM 字节码 / JS / Native(多平台) |
| 类型系统 | 静态类型 | 静态类型 + 流推断 + 空安全 |
1. 空安全(Null Safety)
这是 Kotlin 最常被提起的优势。
Java:
String name = null;
int len = name.length(); // NullPointerException,运行时炸
Kotlin:
var name: String = "hello"
name = null // 编译报错:String 不允许 null
var name2: String? = null // String? 才允许 null
val len = name2?.length // 安全调用,name2 为 null 时返回 null
val len2 = name2?.length ?: 0 // Elvis 运算符,null 时给默认值 0
小结:Java 的空指针是运行时问题;Kotlin 把它前移到了编译期。
2. 语法简洁度
同样的数据类,写法差异很大。
Java:
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public boolean equals(Object o) { /* ... */ }
@Override
public int hashCode() { /* ... */ }
@Override
public String toString() { /* ... */ }
}
Kotlin:
data class User(var name: String, var age: Int)
data class自动生成equals()、hashCode()、toString()、copy()、componentN()。
小结:样板代码(boilerplate)大幅减少。
3. 函数与 Lambda
Java(需要函数式接口):
List<String> upper = names.stream()
.map(String::toUpperCase)
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
Kotlin(一等函数类型):
val upper = names
.map { it.uppercase() }
.filter { it.length > 3 }
Kotlin 的集合操作直接挂在类型上,不需要
.stream()再.collect();it是单参数 lambda 的隐式参数名。
4. 扩展函数
Kotlin 可以给已有类"追加"方法,而不修改其源码或继承。
Kotlin:
fun String.shout(): String = this.uppercase() + "!!!"
println("hello".shout()) // HELLO!!!
Java 没有等价语法,只能写工具方法 StringUtils.shout("hello")。
5. 智能类型转换(Smart Cast)
Java:
if (obj instanceof String) {
String s = (String) obj; // 必须显式强转
System.out.println(s.length());
}
Kotlin:
if (obj is String) {
println(obj.length) // 编译器自动知道 obj 是 String,无需强转
}
6. 类与继承
Java:
public class Animal {
public String sound() { return "..."; }
}
public class Dog extends Animal { // 默认可继承
@Override
public String sound() { return "Woof"; }
}
Kotlin:
open class Animal { // 默认 final,要可继承得加 open
open fun sound(): String = "..."
}
class Dog : Animal() { // 继承用冒号
override fun sound() = "Woof"
}
Kotlin 类默认
final,鼓励组合优于继承;Java 默认可继承。
7. 密封类 / when 表达式
Kotlin 的 sealed class + when 可以做穷尽匹配,编译器会提醒你是否漏了分支。
sealed class Result
data class Success(val data: String) : Result()
data class Error(val msg: String) : Result()
fun handle(r: Result) = when (r) {
is Success -> println("OK: ${r.data}")
is Error -> println("Err: ${r.msg}")
}
// 如果以后加了新子类,这里编译会报错提醒你补分支
Java 17+ 有 sealed + switch 模式匹配,思路类似,但语法更重。
8. 协程 vs 线程
Kotlin 协程:
suspend fun fetchUser(): User {
delay(1000) // 非阻塞等待
return User("Alice", 30)
}
// 启动
GlobalScope.launch {
val user = fetchUser()
println(user)
}
协程是轻量级"线程",一个线程上可以跑十万级协程;写异步代码像写同步代码。
Java: 传统用 Thread / ExecutorService / CompletableFuture,Java 21 引入了虚拟线程(Virtual Thread / Project Loom),思路和协程接近,但生态还在追赶。
9. 互操作
| 方向 | 兼容性 |
|---|---|
| Kotlin 调 Java | 几乎无缝,直接用 |
| Java 调 Kotlin | 可以,但 Kotlin 特有语法(扩展函数、默认参数等)需通过 @JvmStatic / @JvmOverloads 等注解辅助 |
这也是 Kotlin 能在 Android 和后端快速铺开的关键——不需要重写整个项目,可以逐文件迁移。
10. 生态与适用场景
| 维度 | Java | Kotlin |
|---|---|---|
| Android 官方语言 | 曾是,现为 Kotlin | ✅ 2017 起官方首选 |
| 后端(Spring) | ✅ 绝对主力 | ✅ Spring Boot 2.x+ 一等支持 |
| 大数据(Hadoop/Spark/Flink) | ✅ 原生 | 可用,但生态以 Java/Scala 为主 |
| 前端 | ❌ | 可编译为 JS(Kotlin/JS) |
| 原生 | GraalVM | Kotlin/Native 直接支持 |
| 学习曲线 | 平缓,资料极多 | 稍陡,但官方文档质量高 |
| 编译速度 | 快 | 略慢(增量编译在改善) |
| 社区规模 | 极大 | 大且活跃增长中 |
速查表
| 特性 | Java | Kotlin |
|---|---|---|
| 空安全 | ❌ 运行时 NPE | ✅ 编译期 |
| 数据类 | ❌ 需 Lombok 或手写 | ✅ data class |
| 扩展函数 | ❌ | ✅ |
| 智能转换 | ❌ 需显式 cast | ✅ |
| 属性(property) | ❌ field + getter/setter | ✅ 一等公民 |
| 字符串模板 | ❌(String.format) |
✅ "$name has ${list.size}" |
| 默认参数 | ❌(需重载) | ✅ |
| 命名参数 | ❌ | ✅ |
| 单例对象 | 需手写或枚举 | object 关键字一行搞定 |
| 区间 / Range | ❌ | ✅ for (i in 1..10) |
| 协程 | ❌(有 Loom 虚拟线程) | ✅ |
| 密封类穷尽匹配 | Java 17+ 有 | ✅ 成熟 |
该选哪个?
- 已有大型 Java 项目:继续用 Java,或渐进引入 Kotlin(互操作允许混用)。
- 新 Android 项目:选 Kotlin,没有理由不选。
- 新后端项目(Spring):两者都行。团队对 Kotlin 有信心就上;否则 Java 依然是稳妥之选。
- 大数据生态:Java 更顺滑,Scala/Kotlin 视团队熟悉度。
- 追求代码简洁、减少 NPE:Kotlin 体验明显更好。
- 点赞
- 收藏
- 关注作者
评论(0)