Skip to content

运算符

概述

Kotlin提供了丰富的运算符集合,包括算术、比较、逻辑、位运算等。Kotlin的运算符重载机制允许为自定义类型定义运算符行为,使代码更加直观和易读。

算术运算符

基本算术运算

kotlin
fun main() {
    val a = 10
    val b = 3
    
    println("算术运算符示例:")
    println("a = $a, b = $b")
    println("a + b = ${a + b}")  // 加法
    println("a - b = ${a - b}")  // 减法
    println("a * b = ${a * b}")  // 乘法
    println("a / b = ${a / b}")  // 除法(整数除法)
    println("a % b = ${a % b}")  // 取余
    
    // 浮点数运算
    val x = 10.0
    val y = 3.0
    println("\n浮点数运算:")
    println("x = $x, y = $y")
    println("x / y = ${x / y}")  // 浮点除法
    
    // 一元运算符
    println("\n一元运算符:")
    println("+a = ${+a}")   // 一元加
    println("-a = ${-a}")   // 一元减
    println("++a = ${++a}") // 前置递增(注意:这里a的值会改变)
    println("a-- = ${a--}") // 后置递减
    println("a = $a")       // 查看a的最终值
}

复合赋值运算符

kotlin
fun main() {
    var number = 10
    
    println("初始值: $number")
    
    number += 5   // 等同于 number = number + 5
    println("number += 5: $number")
    
    number -= 3   // 等同于 number = number - 3
    println("number -= 3: $number")
    
    number *= 2   // 等同于 number = number * 2
    println("number *= 2: $number")
    
    number /= 4   // 等同于 number = number / 4
    println("number /= 4: $number")
    
    number %= 3   // 等同于 number = number % 3
    println("number %= 3: $number")
}

比较运算符

相等性和比较

kotlin
fun main() {
    val a = 10
    val b = 20
    val c = 10
    
    println("比较运算符示例:")
    println("a = $a, b = $b, c = $c")
    
    // 相等性比较
    println("a == b: ${a == b}")   // 结构相等
    println("a == c: ${a == c}")
    println("a != b: ${a != b}")   // 不等
    
    // 大小比较
    println("a < b: ${a < b}")     // 小于
    println("a > b: ${a > b}")     // 大于
    println("a <= c: ${a <= c}")   // 小于等于
    println("a >= c: ${a >= c}")   // 大于等于
    
    // 引用相等性
    val str1 = "Hello"
    val str2 = "Hello"
    val str3 = String("Hello".toCharArray())
    
    println("\n引用相等性:")
    println("str1 == str2: ${str1 == str2}")   // 结构相等:true
    println("str1 === str2: ${str1 === str2}") // 引用相等:true(字符串池)
    println("str1 == str3: ${str1 == str3}")   // 结构相等:true
    println("str1 === str3: ${str1 === str3}") // 引用相等:false
}

可空类型的比较

kotlin
fun main() {
    val a: Int? = 10
    val b: Int? = null
    val c: Int? = 10
    
    println("可空类型比较:")
    println("a = $a, b = $b, c = $c")
    
    // 安全比较
    println("a == b: ${a == b}")   // false
    println("a == c: ${a == c}")   // true
    println("b == null: ${b == null}")  // true
    
    // 使用安全调用进行比较
    println("a?.compareTo(c ?: 0): ${a?.compareTo(c ?: 0)}")
}

逻辑运算符

布尔逻辑

kotlin
fun main() {
    val isTrue = true
    val isFalse = false
    
    println("逻辑运算符示例:")
    println("isTrue = $isTrue, isFalse = $isFalse")
    
    // 逻辑与
    println("isTrue && isFalse: ${isTrue && isFalse}")
    println("isTrue && isTrue: ${isTrue && isTrue}")
    
    // 逻辑或
    println("isTrue || isFalse: ${isTrue || isFalse}")
    println("isFalse || isFalse: ${isFalse || isFalse}")
    
    // 逻辑非
    println("!isTrue: ${!isTrue}")
    println("!isFalse: ${!isFalse}")
    
    // 短路求值
    println("\n短路求值示例:")
    fun expensiveOperation(): Boolean {
        println("执行昂贵操作")
        return true
    }
    
    println("false && expensiveOperation(): ${false && expensiveOperation()}")  // 不会执行
    println("true || expensiveOperation(): ${true || expensiveOperation()}")    // 不会执行
}

位运算符

位操作

kotlin
fun main() {
    val a = 0b1010  // 10 in decimal
    val b = 0b1100  // 12 in decimal
    
    println("位运算符示例:")
    println("a = $a (${a.toString(2)})")
    println("b = $b (${b.toString(2)})")
    
    // 位运算
    println("a shl 1 = ${a shl 1} (${(a shl 1).toString(2)})")  // 左移
    println("a shr 1 = ${a shr 1} (${(a shr 1).toString(2)})")  // 算术右移
    println("a ushr 1 = ${a ushr 1} (${(a ushr 1).toString(2)})") // 逻辑右移
    
    println("a and b = ${a and b} (${(a and b).toString(2)})")   // 按位与
    println("a or b = ${a or b} (${(a or b).toString(2)})")      // 按位或
    println("a xor b = ${a xor b} (${(a xor b).toString(2)})")   // 按位异或
    println("a.inv() = ${a.inv()} (${a.inv().toString(2)})")     // 按位取反
    
    // 实际应用:权限检查
    println("\n权限检查示例:")
    val READ = 1    // 0001
    val WRITE = 2   // 0010
    val EXECUTE = 4 // 0100
    
    var permissions = READ or WRITE  // 0011
    println("初始权限: ${permissions.toString(2)}")
    
    // 检查权限
    println("有读权限: ${(permissions and READ) != 0}")
    println("有写权限: ${(permissions and WRITE) != 0}")
    println("有执行权限: ${(permissions and EXECUTE) != 0}")
    
    // 添加权限
    permissions = permissions or EXECUTE
    println("添加执行权限后: ${permissions.toString(2)}")
    println("有执行权限: ${(permissions and EXECUTE) != 0}")
}

区间运算符

区间创建和操作

kotlin
fun main() {
    // 闭区间
    val range1 = 1..10        // 1到10(包含10)
    val range2 = 'a'..'z'     // 字符区间
    
    // 开区间
    val range3 = 1 until 10   // 1到9(不包含10)
    
    // 递减区间
    val range4 = 10 downTo 1  // 10到1
    
    println("区间运算符示例:")
    println("1..10: $range1")
    println("'a'..'z': $range2")
    println("1 until 10: $range3")
    println("10 downTo 1: $range4")
    
    // 区间检查
    val number = 5
    println("\n区间检查:")
    println("$number in 1..10: ${number in range1}")
    println("$number !in 1..10: ${number !in range1}")
    
    // 字符区间检查
    val char = 'm'
    println("'$char' in 'a'..'z': ${char in range2}")
    
    // 区间遍历
    println("\n区间遍历:")
    print("1..5: ")
    for (i in 1..5) {
        print("$i ")
    }
    println()
    
    print("10 downTo 6 step 2: ")
    for (i in 10 downTo 6 step 2) {
        print("$i ")
    }
    println()
}

类型检查和转换运算符

is 和 as 运算符

kotlin
fun main() {
    val items: List<Any> = listOf("Hello", 42, 3.14, true, null)
    
    println("类型检查和转换:")
    for (item in items) {
        when {
            item is String -> {
                // 智能转换:item自动转换为String类型
                println("字符串: '$item', 长度: ${item.length}")
            }
            item is Int -> {
                println("整数: $item, 平方: ${item * item}")
            }
            item is Double -> {
                println("浮点数: $item, 四舍五入: ${item.toInt()}")
            }
            item is Boolean -> {
                println("布尔值: $item")
            }
            item == null -> {
                println("空值")
            }
            else -> {
                println("未知类型: $item")
            }
        }
    }
    
    // 类型转换
    println("\n类型转换示例:")
    val obj: Any = "Hello, Kotlin!"
    
    // 不安全转换
    try {
        val str = obj as String
        println("转换成功: $str")
    } catch (e: ClassCastException) {
        println("转换失败: ${e.message}")
    }
    
    // 安全转换
    val str: String? = obj as? String
    val int: Int? = obj as? Int
    
    println("安全转换String: $str")
    println("安全转换Int: $int")
}

Elvis 运算符

空值处理

kotlin
fun main() {
    val nullableString: String? = null
    val anotherNullable: String? = "Hello"
    
    // Elvis运算符 ?:
    val result1 = nullableString ?: "默认值"
    val result2 = anotherNullable ?: "默认值"
    
    println("Elvis运算符示例:")
    println("nullableString ?: '默认值' = '$result1'")
    println("anotherNullable ?: '默认值' = '$result2'")
    
    // 链式Elvis运算符
    val first: String? = null
    val second: String? = null
    val third: String? = "第三个值"
    
    val chainResult = first ?: second ?: third ?: "最终默认值"
    println("链式Elvis: '$chainResult'")
    
    // 与函数调用结合
    fun getName(): String? = null
    fun getDefaultName(): String = "默认姓名"
    
    val name = getName() ?: getDefaultName()
    println("函数调用结合: '$name'")
    
    // 提前返回
    fun processUser(user: User?) {
        val validUser = user ?: return  // 如果user为null,直接返回
        println("处理用户: ${validUser.name}")
    }
    
    processUser(null)
    processUser(User("Alice"))
}

data class User(val name: String)

运算符重载

自定义运算符

kotlin
data class Point(val x: Int, val y: Int) {
    // 重载加法运算符
    operator fun plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
    
    // 重载减法运算符
    operator fun minus(other: Point): Point {
        return Point(x - other.x, y - other.y)
    }
    
    // 重载乘法运算符(标量乘法)
    operator fun times(scalar: Int): Point {
        return Point(x * scalar, y * scalar)
    }
    
    // 重载一元减运算符
    operator fun unaryMinus(): Point {
        return Point(-x, -y)
    }
    
    // 重载比较运算符
    operator fun compareTo(other: Point): Int {
        val thisDistance = x * x + y * y
        val otherDistance = other.x * other.x + other.y * other.y
        return thisDistance.compareTo(otherDistance)
    }
}

// 扩展运算符重载
operator fun Int.times(point: Point): Point {
    return Point(this * point.x, this * point.y)
}

fun main() {
    val point1 = Point(3, 4)
    val point2 = Point(1, 2)
    
    println("运算符重载示例:")
    println("point1 = $point1")
    println("point2 = $point2")
    
    // 使用重载的运算符
    println("point1 + point2 = ${point1 + point2}")
    println("point1 - point2 = ${point1 - point2}")
    println("point1 * 2 = ${point1 * 2}")
    println("3 * point1 = ${3 * point1}")
    println("-point1 = ${-point1}")
    
    // 比较运算符
    println("point1 > point2: ${point1 > point2}")
    println("point1 < point2: ${point1 < point2}")
}

集合运算符重载

kotlin
class Matrix(private val data: Array<IntArray>) {
    val rows = data.size
    val cols = if (rows > 0) data[0].size else 0
    
    // 重载索引访问运算符
    operator fun get(row: Int, col: Int): Int {
        return data[row][col]
    }
    
    operator fun set(row: Int, col: Int, value: Int) {
        data[row][col] = value
    }
    
    // 重载contains运算符
    operator fun contains(value: Int): Boolean {
        return data.any { row -> row.contains(value) }
    }
    
    // 重载迭代器
    operator fun iterator(): Iterator<Int> {
        return data.flatten().iterator()
    }
    
    override fun toString(): String {
        return data.joinToString("\n") { row ->
            row.joinToString(" ") { "%3d".format(it) }
        }
    }
}

fun main() {
    val matrix = Matrix(arrayOf(
        intArrayOf(1, 2, 3),
        intArrayOf(4, 5, 6),
        intArrayOf(7, 8, 9)
    ))
    
    println("矩阵运算符重载:")
    println(matrix)
    
    // 使用索引访问
    println("\nmatrix[1, 1] = ${matrix[1, 1]}")
    
    // 修改元素
    matrix[1, 1] = 10
    println("修改后 matrix[1, 1] = ${matrix[1, 1]}")
    
    // 使用contains
    println("矩阵包含5: ${5 in matrix}")
    println("矩阵包含15: ${15 in matrix}")
    
    // 迭代
    print("所有元素: ")
    for (element in matrix) {
        print("$element ")
    }
    println()
}

运算符优先级

优先级示例

kotlin
fun main() {
    println("运算符优先级示例:")
    
    // 算术运算符优先级
    val result1 = 2 + 3 * 4      // 14, 不是 20
    val result2 = (2 + 3) * 4    // 20
    println("2 + 3 * 4 = $result1")
    println("(2 + 3) * 4 = $result2")
    
    // 比较和逻辑运算符
    val a = 5
    val b = 10
    val c = 15
    
    val result3 = a < b && b < c  // true && true = true
    val result4 = a < b || b > c  // true || false = true
    println("$a < $b && $b < $c = $result3")
    println("$a < $b || $b > $c = $result4")
    
    // Elvis运算符优先级
    val nullable: String? = null
    val result5 = nullable?.length ?: 0
    println("nullable?.length ?: 0 = $result5")
    
    // 赋值运算符优先级最低
    var x = 0
    x += 2 * 3  // x = x + (2 * 3) = 6
    println("x += 2 * 3, x = $x")
}

实际应用示例

数学向量类

kotlin
data class Vector2D(val x: Double, val y: Double) {
    // 向量加法
    operator fun plus(other: Vector2D) = Vector2D(x + other.x, y + other.y)
    
    // 向量减法
    operator fun minus(other: Vector2D) = Vector2D(x - other.x, y - other.y)
    
    // 标量乘法
    operator fun times(scalar: Double) = Vector2D(x * scalar, y * scalar)
    
    // 点积
    infix fun dot(other: Vector2D) = x * other.x + y * other.y
    
    // 向量长度
    val magnitude: Double
        get() = kotlin.math.sqrt(x * x + y * y)
    
    // 单位向量
    fun normalize(): Vector2D {
        val mag = magnitude
        return if (mag != 0.0) Vector2D(x / mag, y / mag) else Vector2D(0.0, 0.0)
    }
    
    override fun toString() = "Vector2D(%.2f, %.2f)".format(x, y)
}

// 扩展运算符
operator fun Double.times(vector: Vector2D) = vector * this

fun main() {
    val v1 = Vector2D(3.0, 4.0)
    val v2 = Vector2D(1.0, 2.0)
    
    println("向量运算示例:")
    println("v1 = $v1")
    println("v2 = $v2")
    println("v1 + v2 = ${v1 + v2}")
    println("v1 - v2 = ${v1 - v2}")
    println("v1 * 2.0 = ${v1 * 2.0}")
    println("2.0 * v1 = ${2.0 * v1}")
    println("v1 dot v2 = ${v1 dot v2}")
    println("v1 magnitude = ${v1.magnitude}")
    println("v1 normalized = ${v1.normalize()}")
}

最佳实践

1. 运算符重载原则

kotlin
// 好的做法:运算符语义应该直观
data class Money(val amount: Double, val currency: String) {
    operator fun plus(other: Money): Money {
        require(currency == other.currency) { "货币类型不匹配" }
        return Money(amount + other.amount, currency)
    }
    
    operator fun times(multiplier: Double): Money {
        return Money(amount * multiplier, currency)
    }
}

// 避免:不直观的运算符重载
// class User {
//     operator fun plus(other: User): User { ... }  // 用户相加没有明确含义
// }

2. 空安全运算符使用

kotlin
// 好的做法:合理使用空安全运算符
fun processUser(user: User?) {
    // 使用安全调用
    val name = user?.name ?: "Unknown"
    
    // 使用let避免重复的空检查
    user?.let { u ->
        println("处理用户: ${u.name}")
        // 更多操作...
    }
}

// 避免:过度使用非空断言
fun badExample(user: User?) {
    // 危险:可能抛出KotlinNullPointerException
    // println(user!!.name)
}

3. 运算符优先级

kotlin
// 好的做法:使用括号明确优先级
fun calculateScore(base: Int, multiplier: Int, bonus: Int): Int {
    return (base * multiplier) + bonus  // 明确优先级
}

// 避免:依赖隐式优先级可能导致混淆
fun confusingCalculation(a: Int, b: Int, c: Int): Int {
    return a + b * c  // 可能不够清晰
}

下一步

掌握了运算符的使用后,让我们学习Kotlin的条件语句,包括if表达式和when表达式。

下一章: 条件语句

练习题

  1. 创建一个复数类,实现基本的算术运算符重载
  2. 实现一个分数类,支持分数的四则运算和比较
  3. 编写程序演示所有类型的运算符优先级
  4. 设计一个矩阵类,实现矩阵的基本运算
  5. 创建一个货币类,实现安全的货币运算(考虑汇率和精度问题)

本站内容仅供学习和研究使用。