从 Java 转身的第一步:10 分钟吃透 Kotlin 核心语法
面向「会一点 Java」的 Android 开发者,用尽量少的术语,把第一阶段 Kotlin 必知点讲清楚,并配上可直接运行的小例子。
1. Kotlin 的诞生与定位(是什么 & 为啥学)
- 是谁做的:JetBrains(写 IntelliJ / Android Studio 的那家公司)在 2011 年左右启动 Kotlin,2016 年发布 1.0。
- 为啥重要:2017 年 Google 宣布 Kotlin 成为 Android 官方一等语言,新项目基本都默认用 Kotlin。
- 想解决什么问题
- Java 写起来太啰嗦:大量模板代码(getter/setter、匿名内部类等)。
- Java 容易出 空指针:
NullPointerException一直是噩梦。 - 希望在 不丢失 Java 生态 的前提下,拥有更现代的语法和更强的表达力。
可以简单理解为:Kotlin = 更安全 + 更简洁的 Java 方言,但还能直接用整个 Java 世界。
2. Kotlin 与 JVM / 跨平台(能跑在哪)
-
Kotlin 与 JVM
- Kotlin 源码通过编译器变成 JVM 字节码(
.class),最后仍由 JVM 执行。 - 所以它和 Java 是「同一个平台上的两种语言」,可以互相调用:
- Kotlin 直接调用 Java 类 / 方法;
- Java 也可以调用 Kotlin 编译好的类。
- 对 Android 来说:底层还是 dex → 虚拟机,只是写代码的语法变了。
- Kotlin 源码通过编译器变成 JVM 字节码(
-
跨平台能力(简单认识即可)
- Kotlin/JVM:Android、服务器端(Spring Boot 等)。
- Kotlin/JS:编译成 JavaScript,在浏览器或 Node.js 跑。
- Kotlin/Native:编译成原生代码,可用于 iOS、桌面等。
- Kotlin Multiplatform:核心业务逻辑一份代码,Android/iOS/shared 均可复用,只在 UI 层分别实现。
对于你现在阶段,只要记住一句:写 Android 用 Kotlin,不会限制你用任何 Java 库,反而更舒服。
3. 变量声明:val / var、类型推断、只读 vs 可变
3.1 基本语法
val:只读引用(类似 Java 的final变量)var:可变引用
val name: String = "Tom" // 只读变量,不能再指向别的字符串
var age: Int = 18 // 可变变量,后面可以改
age = 19 // OK
// name = "Jerry" // 编译错误:Val cannot be reassigned
「只读」指的是变量名不能再指向别的对象,不是说对象本身一定不能改。
val list = mutableListOf(1, 2, 3)
// list = mutableListOf(4, 5) ❌ 不行,list 引用不能变
list.add(4) // ✅ 可以,list 指向的集合本身可以修改
3.2 类型推断(编译器帮你补类型)
val x = 10 // 推断为 Int
val msg = "hi" // 推断为 String
val isLogin = true // 推断为 Boolean
你可以理解为:右边很明确时,左边类型可以不写;不明确时,再显式写类型。
4. 内置数据类型 & 可空 / 不可空
4.1 基本数据类型(本质是类)
- 数值:
Byte,Short,Int,Long,Float,Double - 布尔:
Boolean - 字符:
Char - 字符串:
String
使用方式跟 Java 类似,只是 Kotlin 把它们都当成类(编译时再尽量映射到 JVM 基本类型):
val count: Int = 3
val price: Double = 12.5
val ok: Boolean = true
val ch: Char = 'A'
val text: String = "Hello Kotlin"
4.2 可空类型 vs 不可空类型
- 不可为 null:
String - 可以为 null:
String?(多了一个问号)
var s1: String = "abc"
// s1 = null // ❌ 编译不通过
var s2: String? = "abc"
s2 = null // ✅ 合法
这就是 Kotlin 的空安全基础:编译器强迫你在类型层面区分「可能为 null」和「一定不为 null」,从语法上减少 NPE。
5. 编译期常量:const val
概念:在编译阶段就能确定值的常量,通常用来当全局常量 / 配置 key。
const val TAG = "MainActivity" // 顶层或 object/companion 中
object ApiConfig {
const val BASE_URL = "https://api.example.com"
}
限制:
- 只能修饰
val - 只能用于:顶层、
object、companion object - 右侧必须是编译期字面量(基本类型值、字符串等)
6. 区间(Range)与 when 表达式
6.1 区间(Range)
Range 就是「从 A 到 B 的连续整数」,常用写法:
for (i in 1..5) {
println(i) // 1,2,3,4,5
}
for (i in 1 until 5) {
println(i) // 1,2,3,4(不含 5)
}
for (i in 5 downTo 1) {
println(i) // 5,4,3,2,1
}
val x = 7
if (x in 1..10) { // 判断是否在某个范围内
println("x 在 1~10 之间")
}
6.2 when:更强的 switch
概念:when 是 Kotlin 中更灵活的条件分支语法,可以看作「超级版 switch」。
fun scoreLevel(score: Int): String {
return when (score) {
in 90..100 -> "A"
in 80..89 -> "B"
in 60..79 -> "C"
in 0..59 -> "D"
else -> "非法分数"
}
}
特点:
- 支持 值匹配、区间匹配、类型匹配,甚至可以不写参数:
fun describe(obj: Any): String =
when (obj) {
is String -> "这是字符串,长度=${obj.length}"
is Int -> "这是 Int,值=$obj"
else -> "未知类型"
}
7. 字符串与字符串模板
7.1 普通字符串 & 多行字符串
val s1 = "Hello Kotlin"
val s2 = """
多行字符串
可以直接换行
""".trimIndent()
trimIndent() 会自动去掉多余的缩进,让排版更舒服。
7.2 字符串模板(插值)
概念:在字符串里直接插入变量或表达式,而不用拼接
+。
val name = "Tom"
val age = 18
val s = "$name 今年 $age 岁" // 直接用 $变量名
val s2 = "名字长度 = ${name.length}" // 表达式用 ${...}
8. 函数:声明、默认参数、具名参数
8.1 函数头 = 返回值类型 + 名字 + 参数列表
// 有返回值
fun add(a: Int, b: Int): Int {
return a + b
}
// 没有返回值(等价于返回 Unit)
fun printSum(a: Int, b: Int) {
println(a + b)
}
8.2 参数默认值
概念:在函数定义时给参数一个默认值,调用时可以省略这个参数。
fun greet(name: String = "游客", prefix: String = "你好") {
println("$prefix,$name")
}
greet() // 输出:你好,游客
greet("小明") // 输出:你好,小明
greet(prefix = "早上好") // 输出:早上好,游客
8.3 具名参数(命名参数)
概念:调用函数时,显式写出参数名,提升可读性并支持换顺序。
fun drawRect(width: Int, height: Int, color: String) { ... }
// 普通调用
drawRect(100, 50, "red")
// 具名参数调用
drawRect(
width = 100,
color = "red",
height = 50, // 参数顺序可以调整
)
9. Unit 函数与 Nothing 类型(返回值语义)
9.1 Unit:相当于 Java 的 void
概念:函数正常结束,但「没有有用的返回值」。
fun log(msg: String): Unit {
println("LOG: $msg")
}
// 返回类型可以省略
fun log2(msg: String) {
println("LOG2: $msg")
}
- 在 Kotlin 中,
Unit是一个真实的类型,有一个唯一的值Unit,但你很少需要手动用到它。
10. 反引号中的函数名(`函数名`)
概念:用反引号把「不合法/奇怪的标识符」包起来,也能当函数名/变量名使用。
常见用途:
-
兼容 Java 关键字或奇怪的方法名
// Java 里有个方法名叫 in() fun `in`(x: Int) { println("x = $x") } fun main() { `in`(10) } -
测试代码里写接近自然语言的函数名
@Test fun `should return user when id is valid`() { // 测试逻辑 }
调用时同样需要加反引号,这只是语法糖,方便表达含义。
11. 小结:这一阶段你需要真正掌握的点
- 能够熟练区分并使用:
val/var- 普通类型 vs 可空类型(
String/String?) - 基本类型、字符串、字符串模板
- 能读懂并写出:
- 简单的
when、for (i in 1..n)区间循环 - 有返回值 / 无返回值的函数
- 带默认值、具名参数的函数调用
- 简单的
- 能理解:
const val与普通val的差异Unit/Nothing的语义大概是什么- 反引号函数名只是语法糖,主要用在兼容/测试场景
做到这些,你已经可以把项目里部分简单的 Java 类改写成 Kotlin,并大致看懂 Kotlin 代码。
下一阶段可以继续学习:空安全操作符(?.、?:、!!)、数据类、集合操作、lambda、高阶函数、扩展函数等,这些才是 Kotlin 真正「好用」的地方。

432

被折叠的 条评论
为什么被折叠?



