Kotlin 变量与函数
Kotlin 是一门静态类型语言,运行在 Java 虚拟机之上。它的变量和函数设计既保持了与 Java 的兼容,又引入了许多更简洁的写法。下面从最基础的概念开始介绍。
变量声明
Kotlin 声明变量使用两个关键字:val 和 var。
val表示不可变的引用。一旦赋值,就不能再指向另一个对象。这类似 Java 里的final变量。var表示可变的引用。可以随时改变它指向的对象。
kotlin
val name: String = "Alice" // 只读
var age: Int = 25 // 可读写
age = 26 // 允许
// name = "Bob" // 这行会报编译错误
要注意的是,val 只保证引用不变,并不保证对象内部状态不变。比如:
kotlin
val list = mutableListOf(1, 2, 3)
list.add(4) // 允许,list 这个引用没变
// list = mutableListOf(5) // 不允许,因为 list 是 val
通常,如果一个变量在初始化后不再改变,就使用 val,这样能让代码更易理解。
类型推导
Kotlin 可以根据初始化表达式的值自动推断出变量的类型,所以大部分时候可以不写类型声明。
kotlin
val message = "Hello" // 编译器推断为 String
var count = 100 // 推断为 Int
但有些场合需要显式写出类型:
- 变量没有立刻初始化(比如先声明,后面再赋值)。
- 希望变量使用接口类型而不是具体实现类,例如声明为
List<String>而实际赋值ArrayList。 - 避免数字类型被错误推断,例如
val number = 100L明确指定长整型,或者写成val number: Long = 100。
对于需要延迟初始化的可变变量,可以使用 lateinit。这只能用于 var,且不能是基本类型(如 Int、Double 等)。
kotlin
lateinit var description: String
// 后面的代码中再赋值
description = "Delayed"
属性与访问器
在类里面声明的变量称为属性(property)。每个属性都会自动生成默认的 getter(对于 val)和 setter(对于 var)。你也可以自己编写访问器。
kotlin
class Circle(val radius: Double) {
val area: Double
get() = Math.PI * radius * radius // 每次访问时计算
}
对于 var 属性,可以自定义 setter,例如添加校验逻辑:
kotlin
var temperature: Int = 0
set(value) {
if (value >= -273) {
field = value // field 代表背后的存储字段
}
}
函数定义
函数使用 fun 关键字,返回类型写在参数列表后面。
kotlin
fun add(a: Int, b: Int): Int {
return a + b
}
如果函数体只有一个表达式,可以简化为表达式体,省略花括号和 return:
kotlin
fun add(a: Int, b: Int) = a + b // 返回类型自动推断为 Int
默认参数与命名参数
Kotlin 允许给函数参数设定默认值,这样调用时可以不传该参数。
kotlin
fun greet(name: String, prefix: String = "Hello") {
println("$prefix, $name")
}
// 调用
greet("Tom") // 输出 Hello, Tom
greet("Tom", "Hi") // 输出 Hi, Tom
命名参数允许在调用时指定参数名称,这样参数顺序可以任意调整,也提高了可读性。
kotlin
greet(prefix = "Good morning", name = "Tom")
可变参数
使用 vararg 关键字可以让函数接受任意数量的同类型参数。
kotlin
fun sum(vararg numbers: Int): Int {
return numbers.sum()
}
sum(1, 2, 3, 4) // 返回 10
局部函数
在函数内部还可以定义另一个函数,这称为局部函数。它通常用来封装仅在当前函数内需要重复使用的逻辑。
kotlin
fun process(input: String) {
fun validate(s: String): Boolean {
return s.isNotBlank()
}
if (validate(input)) {
// 处理 input
}
}
局部函数可以访问外层函数的参数和局部变量。
函数类型与高阶函数
Kotlin 中函数也是一种类型,可以将函数作为参数传递给另一个函数,或者作为返回值。函数类型的写法是 (参数类型) -> 返回类型。
kotlin
fun operate(x: Int, y: Int, op: (Int, Int) -> Int): Int {
return op(x, y)
}
val result = operate(10, 5) { a, b -> a - b } // 结果为 5
这样的特性让集合操作(如 map、filter)变得很方便。
作用域与可见性
变量和函数的作用域由声明的位置决定:
- 在文件顶层声明的,属于全局范围,但可以用
private限制仅当前文件可见。 - 在类内部声明的,属于该类的成员。
- 在函数内部声明的,只在该函数内有效。
可见性修饰符有 private、protected、internal、public,默认是 public。
空安全
Kotlin 的类型系统区分可空类型和不可空类型。在类型后面加 ? 表示可以为 null。
kotlin
var nullable: String? = null
var nonNull: String = "value"
// nonNull = null // 编译错误,不允许
函数参数和返回值也遵循这个规则。当访问可空对象的成员时,需要使用安全调用 ?. 或者非空断言 !!(!! 要谨慎使用,它会在值为 null 时抛出异常)。
kotlin
fun getLength(s: String?): Int {
return s?.length ?: 0 // 如果 s 为 null,返回 0
}
这样可以在编译期避免大量的空指针异常。