Skip to content

Kotlin 快速上手

对于熟悉 Java 的开发者,学习 Kotlin 的过程会非常简单,因为二者有着非常相似的语法和语义,但 Kotlin 也有着很多 Java 所不具备的特性,如空值安全、扩展函数、函数式编程、数据类等,这些特性使得 Kotlin 更加简洁、安全、易用

基础语法

  • main 函数作为 Kotlin 应用程序的入口点
  • var 声明可变变量
  • val 声明不可变变量
  • fun 声明函数
  • 类型声明后置,简单场景可依靠类型推断省略书写
kotlin
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
// 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 / LongFloat / Double 的基本数值类型。但在 Kotlin 中并不区分基本类型和装箱类型,编译后 Int 会映射为 Java 中的 int,而 Int? 会映射为 Java 中的 Integer

Kotlin 在赋值时不支持较小的类型隐式转换为较大的类型(如不支持把 Int 赋值给 Long),需要使用转换函数进行显式转换,转换函数包括:

  • toByte(): Byte
  • toShort(): Short
  • toInt(): Int
  • toLong(): Long
  • toFloat(): Float
  • toDouble(): Double

但在进行算数运算时,依靠运算符的重载,Kotlin 会自动进行一些类型转换:

kotlin
// Int + Double -> Double
val num = 1 + 2.0

字符串

Kotlin 提供了强大的字符串模板功能,可在字符串中直接引用变量、使用表达式或调用函数,而无需进行字符串拼接:

  • 模板表达式以 $ 开头
  • 当引用简单的变量时,可以直接使用 $ 符号,如 $name
  • 当引用表达式时,需要使用 ${} 包裹表达式,如 ${name.length}
  • ${} 中支持复杂表达式,如 ${if (name.length > 10) "long" else "short"}
kotlin
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 循环遍历这些字符:

kotlin
val text = "Hello, Kotlin!"

println(text[0])
for (i in text) { println(i) }

数组

注意

除性能要求等特殊需求外,Kotlin 推荐使用集合而非数组,集合的优势包括:

  • 集合明确区分了可变集合和不可变集合,而数组元素始终可变
  • 集合提供了更丰富的方法和特性,相比数组更易于操作
  • 由于数组的大小固定,对其增删的操作都会创建出新的数组,效率低下

Kotlin 中使用 arrayOf()Array 构造函数创建数组,并通过索引访问运算符 [] 访问或修改数组元素:

kotlin
// 使用 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 中分支能使用的条件非常灵活,可覆盖大部分场景:

kotlin
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() 方法,返回一个迭代器并用于遍历数组或集合中的元素:

kotlin
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 循环,需要使用范围运算符 .. 创建一个区间表达式:

kotlin
// 从 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,并由 = 连接函数体与返回值:

kotlin
fun double(x: Int): Int = x * 2

默认参数

通过在函数参数的类型后面添加 = 来设置参数的默认值,这样可以有效的减少函数重载的情况:

kotlin
fun greet(name: String = "Kotlin") {
    println("Hello, $name!")
}

具名参数

在调用函数时可以指定参数名称,这样可以不用按照参数的定义顺序来传递参数,可以只传递部分参数,对于理解参数值的含义也非常有帮助:

kotlin
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]")
}