Kotlin 快速上手
对于熟悉 Java 的开发者,学习 Kotlin 的过程会非常简单,因为二者有着非常相似的语法和语义,但 Kotlin 也有着很多 Java 所不具备的特性,如空值安全、扩展函数、函数式编程、数据类等,这些特性使得 Kotlin 更加简洁、安全、易用
基础语法
main
函数作为 Kotlin 应用程序的入口点var
声明可变变量val
声明不可变变量fun
声明函数- 类型声明后置,简单场景可依靠类型推断省略书写
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main() {
var a: Int = 1 // 可变变量, 手动指定类型
val b = 2 // 不可变变量, 自动推断类型
println(sum(a, b))
a = 3 // 仅可变变量可以重新赋值
println(sum(a, b))
}
// Java 不支持顶层函数, Kotlin 编译器会依据文件名自动生成一个类
public final class MainKt {
public static final int sum(int a, int b) {
return a + b;
}
public static final void main() {
int a = 1;
int b = 2;
int var2 = sum(a, b);
System.out.println(var2);
a = 3;
var2 = sum(a, b);
System.out.println(var2);
}
public static void main(String[] args) {
main();
}
}
基本类型
数值
Kotlin 与 Java 相同,都提供了 Byte / Short / Int / Long
、Float / Double
的基本数值类型。但在 Kotlin 中并不区分基本类型和装箱类型,编译后 Int
会映射为 Java 中的 int
,而 Int?
会映射为 Java 中的 Integer
Kotlin 在赋值时不支持较小的类型隐式转换为较大的类型(如不支持把 Int
赋值给 Long
),需要使用转换函数进行显式转换,转换函数包括:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
但在进行算数运算时,依靠运算符的重载,Kotlin 会自动进行一些类型转换:
// Int + Double -> Double
val num = 1 + 2.0
字符串
Kotlin 提供了强大的字符串模板功能,可在字符串中直接引用变量、使用表达式或调用函数,而无需进行字符串拼接:
- 模板表达式以
$
开头 - 当引用简单的变量时,可以直接使用
$
符号,如$name
- 当引用表达式时,需要使用
${}
包裹表达式,如${name.length}
${}
中支持复杂表达式,如${if (name.length > 10) "long" else "short"}
val name = "Kotlin"
println("The name $name has ${name.length} characters.")
println("It's a ${if (name.length > 10) "long" else "short"} name.")
// output:
// The name Kotlin has 6 characters.
// It's a short name.
字符串中的各字符可以通过索引运算符 []
访问,也可以使用 for 循环遍历这些字符:
val text = "Hello, Kotlin!"
println(text[0])
for (i in text) { println(i) }
数组
注意
除性能要求等特殊需求外,Kotlin 推荐使用集合而非数组,集合的优势包括:
- 集合明确区分了可变集合和不可变集合,而数组元素始终可变
- 集合提供了更丰富的方法和特性,相比数组更易于操作
- 由于数组的大小固定,对其增删的操作都会创建出新的数组,效率低下
Kotlin 中使用 arrayOf()
或 Array
构造函数创建数组,并通过索引访问运算符 []
访问或修改数组元素:
// 使用 arrayOf() 创建数组
val languages = arrayOf("Kotlin", "Java", "Python")
// 使用索引访问和修改数组元素
println(languages[0])
languages[0] = "C++"
println(languages[0])
// 使用 Array 构造函数创建指定大小的数组, 并初始化元素
val numbers = Array(3) { it * 2 } // 0, 2, 4
for (number in numbers) { println(number) }
流程控制
when 表达式
when
类似于 Java 中的 switch
语句,但省去了 break
的操作且更加灵活。当有三个及更多条件选项时,推荐使用 when
而非 if-else
,其将提供的参数与所有分支条件依次比较,直到满足某个分支条件
when
既可以作为语句也可以作为表达式,当作为表达式时,符合条件分支中末尾的值就是整个表达式的值(if
也可作为表达式,同理)
when
中分支能使用的条件非常灵活,可覆盖大部分场景:
fun describe(obj: Any): String =
when (obj) {
"Hello" -> "Kotlin"
1 -> "One"
in 2..10 -> "Between 2 and 10"
is Long -> "Long"
!is String -> "Not String"
else -> throw Exception("Unknown")
}
fun main() {
// 依次对应上述分支
println(describe("Hello"))
println(describe(1))
println(describe(5))
println(describe(100L))
println(describe(true))
println(describe("true"))
}
for 循环
在数组或集合中使用 for 循环,需要搭配 in
运算符,与 Java 的增强 for 循环类似,该操作会调用对象的 iterator()
方法,返回一个迭代器并用于遍历数组或集合中的元素:
val array = arrayOf("a", "b", "c")
for (item in array) {
println(item)
}
// 使用 indices 遍历索引
for (index in array.indices) {
println("The element at $index is ${array[index]}")
}
// 使用 withIndex() 同时遍历索引和值
for ((index, value) in array.withIndex()) {
println("The element at $index is $value")
}
在区间中使用 for 循环,需要使用范围运算符 ..
创建一个区间表达式:
// 从 1 开始, 遍历到 100 结束
for (i in 1..100) { println(i) }
// 从 a 开始, 遍历到 z 结束
for (i in 'a'..'z') { println(i) }
// 从 1 开始, 到达 100 之前遍历结束, 步进为 2
for (i in 1..<100 step 2) { println(i) }
// 从 100 开始, 遍历到 1 结束, 步进为 2
for (i in 100 downTo 1 step 2) { println(i) }
函数
单表达式函数
当函数体由单个表达式构成时,可以省略 {}
和 return
,并由 =
连接函数体与返回值:
fun double(x: Int): Int = x * 2
默认参数
通过在函数参数的类型后面添加 =
来设置参数的默认值,这样可以有效的减少函数重载的情况:
fun greet(name: String = "Kotlin") {
println("Hello, $name!")
}
具名参数
在调用函数时可以指定参数名称,这样可以不用按照参数的定义顺序来传递参数,可以只传递部分参数,对于理解参数值的含义也非常有帮助:
fun createProfile(
name: String,
age: Int,
gender: String = "Not specified",
email: String = "Not specified"
) {
println("Name: $name")
println("Age: $age")
println("Gender: $gender")
println("Email: $email")
}
fun main() {
// 省略 gender, 直接指定 email
createProfile("Alice", 18, email = "[email protected]")
// 改变参数顺序
createProfile(age = 20, name = "Bob", email = "[email protected]")
}