运算符
概述
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表达式。
下一章: 条件语句
练习题
- 创建一个复数类,实现基本的算术运算符重载
- 实现一个分数类,支持分数的四则运算和比较
- 编写程序演示所有类型的运算符优先级
- 设计一个矩阵类,实现矩阵的基本运算
- 创建一个货币类,实现安全的货币运算(考虑汇率和精度问题)