目录
13.按位运算符 shl、shr、ushr、and、or、xor
一Kotlin运算符详解:
本章内容将会介绍Kotlin的所有运算符及其作用和特性
1.Kotlin的运算符分类
在Kotlin中,运算符是一种特殊的符号或关键词,用于操作数据,Kotlin提供了丰富的运算符并支持运算符重载,使得它在表达式构建方面非常的灵活,接下来,我会依次介绍各种运算符
1.算术运算符
这些运算符主要用于数学运算
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
+ | 加法 | a + b | 两数之和 |
- | 减法 | a - b | 两数之差 |
* | 乘法 | a * b | 两数之积 |
/ | 除法 | a / b | 两数之商 |
% | 求余(模) | a % b | 两数的余数 |
示例:
fun main() {
val a = 10
val b = 3
// 加法运算
println("Addition: ${a + b}") // 13
// 减法运算
println("Subtraction: ${a - b}") // 7
// 乘法运算
println("Multiplication: ${a * b}") // 30
// 除法运算
println("Division: ${a / b}") // 3
// 求余运算
println("Modulus: ${a % b}") // 1
}
2.比较运算符:
用于比较两个值,结果是布尔类型
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
> | 大于 | a > b | true 或 false |
< | 小于 | a < b | true 或 false |
>= | 大于或等于 | a >= b | true 或 false |
<= | 小于或等于 | a <= b | true 或 false |
== | 等于(值比较) | a == b | true 或 false |
!= | 不等于 | a != b | true 或 false |
示例:
fun main() {
val x = 5
val y = 10
// 判断 x 是否大于 y
println(x > y) // false
// 判断 x 是否小于等于 y
println(x <= y) // true
// 判断 x 是否等于 y
println(x == y) // false
// 判断 x 是否不等于 y
println(x != y) // true
}
3. 逻辑运算符 :
用于布尔逻辑运算,结果为布尔值
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
&& | 与(AND) | a && b | true 当且仅当 a 和 b 都为 true |
` | ` | 或(OR) | |
! | 非(NOT) | !a | true 转为 false ,反之亦然 |
示例:
fun main() {
val a = true
val b = false
// 与运算:a 和 b 都为 true 时返回 true
println(a && b) // false
// 或运算:a 或 b 只要有一个为 true 返回 true
println(a || b) // true
// 非运算:取反 a 的值
println(!a) // false
}
4.赋值运算符:
用于将值赋给变量
运算符 | 描述 | 示例 |
---|---|---|
= | 赋值 | a = 10 |
+= | 加并赋值 | a += b 相当于 a = a + b |
-= | 减并赋值 | a -= b 相当于 a = a - b |
*= | 乘并赋值 | a *= b 相当于 a = a * b |
/= | 除并赋值 | a /= b 相当于 a = a / b |
%= | 模并赋值 | a %= b 相当于 a = a % b |
示例:
fun main() {
var a = 10
// 加并赋值:a += 5 相当于 a = a + 5
a += 5
println(a) // 15
// 乘并赋值:a *= 2 相当于 a = a * 2
a *= 2
println(a) // 30
// 减并赋值:a -= 3 相当于 a = a - 3
a -= 3
println(a) // 27
}
5. 位运算符:
用于对位进行操作
运算符 | 描述 | 示例 |
---|---|---|
shl | 左移 | a shl 2 |
shr | 右移 | a shr 2 |
ushr | 无符号右移 | a ushr 2 |
and | 按位与 | a and b |
or | 按位或 | a or b |
xor | 按位异或 | a xor b |
inv | 按位取反 | a.inv() |
示例:
fun main() {
val a = 5 // 二进制:0101
// 左移:将 a 的位左移一位,结果为 1010(二进制)
println(a shl 1) // 10
// 右移:将 a 的位右移一位,结果为 0010(二进制)
println(a shr 1) // 2
// 按位与:a 和 3 按位与,结果为 0001(二进制)
println(a and 3) // 1
// 按位或:a 和 2 按位或,结果为 0111(二进制)
println(a or 2) // 7
}
6. 特殊运算符:
运算符 | 描述 | 示例 |
---|---|---|
in | 检查值是否在集合中 | x in list |
!in | 检查值是否不在集合中 | x !in list |
is | 检查对象是否为特定类型 | x is String |
!is | 检查对象是否不是特定类型 | x !is Int |
示例::
fun main() {
val list = listOf(1, 2, 3)
// 判断 2 是否在 list 中
println(2 in list) // true
// 判断 4 是否不在 list 中
println(4 !in list) // true
val x: Any = "Kotlin"
// 判断 x 是否为 String 类型
println(x is String) // true
// 判断 x 是否不是 Int 类型
println(x !is Int) // true
}
End:
这些分类涵盖了 Kotlin 中的所有运算符。每个运算符都有明确的用途,通过实际代码练习和理解公式逻辑,可以灵活运用在项目开发中
2.运算符优先级:
Kotlin中运算符优先级从高到低分为以下几个层次
1.最高优先级
1.括号运算符()
用于显示地定义计算顺序
( a + b) * c 保证先计算a+b
val result = 5 + 3 * 2
println(result) //输出:11
解释:*的优先级高于+,所以3*2先被计算,结果为6,再计算5+6
若改变括号顺序:
val result = (5 + 3) * 2
println(result) // 输出: 16
2.数组下标和成员访问[] 和 、
arr[0]、obj.property
3.函数调用
myFunction(arg1,arg2)
4.类型转换as、as?
obj as String
2.次高级优先
5.一元运算符
包括
- 正负号:+、-
例: -a
- 递增和递减: ++、--
例 ++a、a--
- 取非: !
例: !isValid
6.按位取反 inv()
- 例: a.inv()
3.中等优先级
7.乘法、除法和取模运算*、/、%
- 例: a * b / c
8.加法和减法+、-
- 例: a+b-c
9.范围运算符、、
- 例: 1..10创建一个从1到10的范围
10.类型检查 is、!is
- 例: a is Int
4.较低优先级
11.比较运算符 <
、<=
、>
、>=
- 示例:
a < b
。
12.等价性运算符 ==
、!=
- 示例:
a == b
。
13.按位运算符 shl
、shr
、ushr
、and
、or
、xor
- 示例:
a and b
。
5.最低优先级
-
逻辑运算符
- 逻辑与:
&&
示例:a && b
。 - 逻辑或:
||
示例:a || b
。
- 逻辑与:
-
赋值运算符
- 简单赋值:
=
- 复合赋值:
+=
、-=
、*=
、/=
、%=
- 示例:
a = b
、a += 2
。
- 简单赋值:
3.运算符重载(进阶内容)
什么是运算重载?
运算重载是Kotlin提供的一种能力,它允许我们为自定义的类定义现有运算符的能力,换句话说,Kotlin中的某些运算符可以通过特殊的函数来重新定义它们的功能
运算重载的核心
1.需要使用operator关键字声明重载函数
2.只能重载Kotlin预定义的运算符
3.函数名必须符合Kotlin运算符对应的函数签名
运算符重载的示例分类
1.数学运算符
- 常见数学运算符
+
、-
、*
、/
、%
都可以被重载
示例:定义一个向量类
// 定义一个数据类 Vector,表示二维向量
data class Vector(val x: Int, val y: Int) {
// 运算符重载函数,重载 + 运算符
operator fun plus(other: Vector): Vector {
// 返回一个新的 Vector,其 x 和 y 是当前向量与另一个向量对应分量相加的结果
return Vector(x + other.x, y + other.y)
}
}
fun main() {
// 创建两个向量实例 v1 和 v2
val v1 = Vector(3, 4) // 第一个向量,x=3, y=4
val v2 = Vector(1, 2) // 第二个向量,x=1, y=2
// 使用 + 运算符对两个向量进行相加
val result = v1 + v2
// 打印相加结果,结果为一个新的 Vector(x=4, y=6)
println(result) // 输出: Vector(x=4, y=6)
}
2.比较运算符
- 重载
>
、<
、>=
、<=
需要实现compareTo
函数。
示例:比较分数大小
// 定义一个表示分数的数据类 Fraction
data class Fraction(val numerator: Int, val denominator: Int) : Comparable<Fraction> {
// 重载 compareTo 运算符,用于比较两个 Fraction 对象
operator fun compareTo(other: Fraction): Int {
// 通过交叉相乘比较两个分数的大小,避免直接浮点数计算
// 计算公式: (a/b ? c/d) 等价于 (a * d ? c * b)
return (this.numerator * other.denominator) - (this.denominator * other.numerator)
// 返回值:
// > 0 表示当前分数大于 other
// < 0 表示当前分数小于 other
// == 0 表示两个分数相等
}
}
fun main() {
// 创建两个分数实例 f1 和 f2
val f1 = Fraction(1, 2) // 分数 f1 表示 1/2
val f2 = Fraction(2, 3) // 分数 f2 表示 2/3
// 使用 < 运算符比较两个分数的大小
// 因为 Fraction 类实现了 Comparable 接口,并重载了 compareTo 方法
println(f1 < f2) // 输出: true
// 解释: 1/2 < 2/3,因为 1*3 (3) 小于 2*2 (4)
}
3.索引运算符
- 使用
get
和set
函数重载[]
运算符。
示例:自定义矩阵
// 定义一个矩阵类 Matrix,用于表示和操作二维矩阵
class Matrix(private val data: Array<IntArray>) {
// 重载 get 运算符,用于通过下标获取矩阵中的元素
operator fun get(row: Int, col: Int): Int {
// 返回指定行和列的元素
return data[row][col]
}
// 重载 set 运算符,用于通过下标设置矩阵中的元素
operator fun set(row: Int, col: Int, value: Int) {
// 将指定位置的元素更新为新的值
data[row][col] = value
}
}
fun main() {
// 创建一个 2x2 的矩阵,初始值为 [[1, 2], [3, 4]]
val matrix = Matrix(arrayOf(intArrayOf(1, 2), intArrayOf(3, 4)))
// 使用自定义的 get 运算符,获取矩阵第 0 行第 1 列的元素
println(matrix[0, 1]) // 输出: 2
// 使用自定义的 set 运算符,将矩阵第 0 行第 1 列的值更新为 99
matrix[0, 1] = 99
// 再次获取矩阵第 0 行第 1 列的值,验证修改是否成功
println(matrix[0, 1]) // 输出: 99
}
4.单目运算符
- 例如
+a
和-a
,需要重载unaryPlus
和unaryMinus
示例:反向编辑
// 定义一个表示二维向量的数据类 Vector
data class Vector(val x: Int, val y: Int) {
// 重载一元运算符 -,用于求向量的相反向量
operator fun unaryMinus(): Vector {
// 返回一个新的 Vector,其 x 和 y 分量分别取反
return Vector(-x, -y)
}
}
fun main() {
// 创建一个向量实例 v,x=3, y=4
val v = Vector(3, 4)
// 使用重载的 - 运算符求相反向量
println(-v) // 输出: Vector(x=-3, y=-4)
}
运算符重载的注意事项
-
语义一致性
重载后的运算符应该符合原本的语义。例如,重载
+
应该表示加法或类似的行为,避免令人困惑的实现。 -
性能考虑
运算符重载本质上是方法调用,频繁使用可能有额外的性能开销。
-
不能重载所有运算符
例如,
&&
和||
是短路运算符,不能被重载。 -
代码可读性
滥用运算符重载可能导致代码难以理解。合理使用可提高可读性,滥用则可能造成混淆。
实战案例(可选):
- 实现一个简单的计算器:支持基础的四则运算,结合用户输入
- 集合操作练习:判断一个数是否在特定区间内,结合表达式进行优化
解:
fun main() {
// 提示
println("请输入表达式(例如:3 + 4):")
// 获取用户输入
val input = readLine() ?: return // 如果输入为空,直接退出程序
// 使用正则表达式匹配输入格式,提取操作数和运算符
val regex = """(\d+)\s*([\+\-\*/])\s*(\d+)""".toRegex()
val matchResult = regex.matchEntire(input)
// 检查输入是否匹配正则表达式
if (matchResult != null) {
// 解构正则匹配结果为三个部分:第一个操作数、运算符、第二个操作数
val (num1, operator, num2) = matchResult.destructured
// 使用 when 处理不同的运算符
val result = when (operator) {
"+" -> num1.toInt() + num2.toInt() // 加法运算
"-" -> num1.toInt() - num2.toInt() // 减法运算
"*" -> num1.toInt() * num2.toInt() // 乘法运算
"/" -> if (num2.toInt() != 0) num1.toInt() / num2.toInt() // 除法运算,检查除数是否为 0
else "除数不能为0"
else -> "未知运算符" // 不支持的运算符
}
// 输出结果
println("结果是:$result")
} else {
// 输入格式不正确时的提示
println("输入格式有误,请检查!")
}
}
fun main() {
// 定义一个区间 1..10,表示 [1, 10] 的所有整数
val range = 1..10
// 定义一个集合,包含一些特定的值
val set = setOf(15, 20, 25, 30)
// 提示用户输入一个数字
println("请输入一个数字:")
val input = readLine()?.toIntOrNull() // 获取用户输入并尝试将其转换为整数
// 检查输入是否为有效数字
if (input != null) {
// 使用 when 表达式判断数字所属范围或集合
when {
input in range -> println("$input 在区间 $range 中") // 输入在区间内
input in set -> println("$input 在集合 $set 中") // 输入在集合内
else -> println("$input 不在区间 $range 和集合 $set 中") // 输入不属于区间和集合
}
} else {
// 输入无效时提示
println("请输入有效的数字!")
}
}
好了,本章内容暂且完结,主要介绍一下运算符下一章会开启全新的内容哦