🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Kotlin 的运算符 > 原文: [http://zetcode.com/kotlin/operators/](http://zetcode.com/kotlin/operators/) 在本教程中,我们将介绍 Kotlin 运算符。 我们展示了如何使用运算符创建表达式。 运算符是特殊符号,表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。 操作数是运算符的输入(参数)之一。 表达式是根据操作数和运算符构造的。 表达式的运算符指示将哪些运算应用于操作数。 表达式中运算符的求值顺序由运算符的优先级和关联性确定。 一个运算符通常有一个或两个操作数。 那些仅使用一个操作数的运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。 某些运算符可以在不同的上下文中使用。 例如,`+`运算符可以在不同的情况下使用:它添加数字,连接字符串或指示数字的符号。 我们说运算符是重载。 ## Kotlin 标志运算符 有两个符号运算符:`+`和`-`。 它们用于指示或更改值的符号。 `KotlinSignOperatorsEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { println(2) println(+2) println(-2) } ``` `+`和`-`符号指示值的符号。 加号可用于表示我们有一个正数。 可以省略它,并且在大多数情况下可以这样做。 `KotlinMinusSignEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val a = 1 println(-a) println(-(-a)) } ``` 减号更改值的符号。 ## Kotlin 赋值运算符 赋值运算符`=`将值赋给变量。 变量是值的占位符。 在数学中,=运算符具有不同的含义。 在等式中,`=`运算符是一个相等运算符。 等式的左边等于右边的等式。 ```kt val x = 1 ``` 在这里,我们为`x`变量分配一个数字。 ```kt x = x + 1 ``` 这个表达式在数学上没有意义,但是在编程中是合法的。 该表达式将`x`变量加 1。 右边等于 2,并且 2 分配给`x`。 ```kt 3 = x ``` 此代码行导致语法错误。 我们无法为字面值分配值。 ## Kotlin 扩展赋值运算子 扩展赋值运算符是由两个运算符组成的速记运算符。 增强的赋值运算符在其他编程语言中也称为复合赋值运算符。 ```kt a = a + 3 a += 3 ``` `+=`复合运算符是这些速记运算符之一。 以上两个表达式相等。 将值 3 添加到变量`a`中。 Kotlin 扩展分配运算符为: ```kt += -= *= /= %= ``` 下面的示例使用两个复合运算符。 `KotlinAugmentedAssignmentOperatorsEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { var a = 1 a = a + 1 println(a) a += 5 println(a) a *= 3 println(a) } ``` 我们使用`+=`和`*=`复合运算符。 ```kt var a = 1 a = a + 1 ``` `a`变量被初始化为 1。 使用非速记符号将值 1 添加到变量。 ```kt a += 5 ``` 使用`+=`复合运算符,将 5 加到`a`变量中。 该语句等于`a = a + 5`。 ```kt a *= 3 ``` 使用`*=`运算符,将`a`乘以 3。该语句等于`a = a * 3`。 ```kt 2 7 21 ``` 这是示例输出。 ## Kotlin 连接字符串 在 Kotlin 中,`+`运算符还用于连接字符串。 `KotlinConcatenateStringsEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { println("Return " + "of " + "the king.") println("Return".plus(" of").plus(" the king.")) } ``` 我们将三个字符串连接在一起。 ```kt println("Return " + "of " + "the king.") ``` 字符串用`+`运算符连接。 ```kt println("Return".plus(" of").plus(" the king.")) ``` 连接字符串的另一种方法是`plus()`方法。 ## Kotlin 增减运算符 将值递增或递减一个是编程中的常见任务。 Kotlin 为此有两个方便的运算符:`++`和`--`。 ```kt x++ x = x + 1 ... y-- y = y - 1 ``` 上面两对表达式的作用相同。 `KotlinIncDecEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { var x = 6 x++ x++ println(x) x-- println(x) } ``` 在上面的示例中,我们演示了两个运算符的用法。 ```kt int x = 6 x++ x++ ``` 将`x`变量初始化为 6。然后将`x`递增两次。 现在变量等于 8。 ```kt x-- ``` 我们使用减量运算符。 现在变量等于 7。 ## Kotlin 算术运算符 下表是 Kotlin 中的算术运算符表。 | 符号 | 名称 | | --- | --- | | `+` | 加法 | | `-` | 减法 | | `*` | 乘法 | | `/` | 乘法 | | `%` | 余数 | 以下示例显示了算术运算。 `KotlinArithmeticOperatorsEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val a = 10 val b = 11 val c = 12 val add = a + b + c val sb = c - a val mult = a * b val div = c / 3 val rem = c % a println(add) println(sb) println(mult) println(div) println(rem) } ``` 在前面的示例中,我们使用加法,减法,乘法,除法和余数运算。 这些都是数学所熟悉的。 ```kt val rem = c % a ``` `%`运算符称为余数或模运算符。 它找到一个数除以另一个的余数。 例如`9 % 4`,9 模 4 为 1,因为 4 两次进入 9 且余数为 1。 整数除法和浮点除法之间有区别。 `KotlinDivisionEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val c = 5 / 2 println(c) val d = 5 / 2.0 println(d) } ``` 在前面的示例中,我们将两个数字相除。 ```kt val c = 5 / 2 ``` 在这段代码中,我们完成了整数除法。 除法运算的返回值为整数。 当我们将两个整数相除时,结果是一个整数。 ```kt val d = 5 / 2.0 ``` 如果值之一是`double`或`float`,则执行浮点除法。 在我们的例子中,第二个操作数是双精度数,因此结果是双精度数。 ```kt 2 2.5 ``` 我们看到了程序的结果。 ## Kotlin 布尔运算符 在 Kotlin 中,我们有三个逻辑运算符。 | 符号 | 名称 | | --- | --- | | `&&` | 逻辑与 | | <code>&#124;&#124;</code> | 逻辑或 | | `!` | 否定 | 布尔运算符也称为逻辑运算符。 `KotlinBooleanExpEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val x = 3 val y = 8 println(x == y) println(y > x) if (y > x) { println("y is greater than x") } } ``` 许多表达式导致布尔值。 例如,在条件语句中使用布尔值。 ```kt println(x == y) println(y > x) ``` 关系运算符始终导致布尔值。 这两行分别显示`false`和`true`。 ```kt if (y > x) { println("y is greater than x") } ``` 仅在满足括号内的条件时才执行`if`语句的主体。 `y > x`返回`true`,因此消息`"y`大于`x"`被打印到终端。 `true`和`false`关键字表示 Kotlin 中的布尔字面值。 `KotlinAndOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val a = true && true val b = true && false val c = false && true val d = false && false println(a) println(b) println(c) println(d) } ``` 该代码示例显示了逻辑和(`&&`)运算符。 仅当两个操作数均为`true`时,它的评估结果为`true`。 ```kt true false false false ``` 只有一个表达式可得出`true`。 如果两个操作数中的任何一个为`true`,则逻辑或(`||`)运算符的计算结果为`true`。 `KotlinOrOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val a = true || true val b = true || false val c = false || true val d = false || false println(a) println(b) println(c) println(d) } ``` 如果运算符的任一侧为真,则操作的结果为真。 ```kt true true true false ``` 四个表达式中的三个表示为`true`。 否定运算符`!`将`true`设为`false`,并将`false`设为`false`。 `KotlinNegationEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { println(! true) println(! false) println(! (4 < 3)) } ``` 该示例显示了否定运算符的作用。 ```kt false true true ``` 这是程序的输出。 ## Kotlin 比较运算符 比较运算符用于比较值。 这些运算符总是产生布尔值。 | 符号 | 含义 | | --- | --- | | `<` | 小于 | | `<=` | 小于或等于 | | `>` | 大于 | | `>=` | 大于或等于 | | `==` | 等于 | | `!=` | 不等于 | 比较运算符也称为关系运算符。 `KotlinComparisonOperatorsEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { println(3 < 4); println(3 == 4); println(4 >= 3); println(4 != 3); } ``` 在代码示例中,我们有四个表达式。 这些表达式比较整数值。 每个表达式的结果为`true`或`false`。 在 Kotlin 中,我们使用`==`比较数字。 (某些语言(例如 Ada,Visual Basic 或 Pascal)使用`=`比较数字。) ## Kotlin 按位运算符 与 Java 不同,Kotlin 中没有按位运算符。 Kotlin 已经命名了执行按位运算的函数。 * `shl(bits)` – 有符号左移(Java 的`<<`) * `shr(bits)` – 有符号右移(Java 的`>>`) * `ushr(bits)` – 无符号右移(Java 的`>>>`) * `and(bits)` – 按位与 * `or(bits)` – 按位或 * `xor(bits)` – 按位异或 * `inv()` – 按位反转 这些函数仅适用于`Int`和`Long`类型。 按位操作在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时,位位置的结果才为 1。 ```kt 00110 & 00011 = 00010 ``` 第一个数字是二进制符号 6,第二个数字是 3,结果是 2。 ```kt println(6 and 3) // prints 2 println(3 and 6) // prints 2 ``` 按位或操作在两个数字之间进行逐位比较。 如果操作数中的任何对应位为 1,则位位置的结果为 1。 ```kt 00110 | 00011 = 00111 ``` 结果为`00110`或十进制 7。 ```kt println(6 or 3) // prints 7 println(3 or 6) // prints 7 ``` ## Kotlin `is`运算符 要在运行时检查对象是否符合给定类型,我们可以使用`is`运算符或其否定形式`!is`。 `KotlinIsOperatorEx.kt` ```kt package com.zetcode open class Base class Derived : Base() fun main(args: Array<String>) { val b = Base() val d = Derived() println(d is Base) println(b is Derived) println(d is Any) } ``` 在示例中,我们有两个类:一个基类和一个从基类派生的类。 ```kt println(d is Base) ``` 此行检查变量`d`是否指向作为`Base`类实例的类。 由于`Derived`类继承自`Base`类,因此它也是`Base`类的实例。 该行打印正确。 ```kt println(b is Derived) ``` `b`对象不是`Derived`类的实例。 该行显示`false`。 ```kt println(d is Any) ``` 每个类都有`Any`作为超类。 因此,`d`对象也是`Any`类的实例。 ```kt true false true ``` 这是程序的输出。 ## Kotlin Lambda 运算符 Kotlin 具有 lambda 运算符(`->`)。 它分隔了 lambda 表达式的参数和主体。 `KotlinLambdaOperatorEx.kt` ```kt package com.zetcode import java.util.Arrays fun main(args: Array<String>) { val words = arrayOf("kind", "massive", "atom", "car", "blue") Arrays.sort(words) { s1: String, s2: String -> s1.compareTo(s2) } println(Arrays.toString(words)) } ``` 在示例中,我们定义了一个字符串数组。 使用`Arrays.sort()`方法和 lambda 表达式对数组进行排序。 ```kt [atom, blue, car, kind, massive] ``` 这是输出。 ## Kotlin 双冒号运算符 双冒号运算符(::)用于创建类或函数引用。 `KotlinDoubleColonOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val c = String::class c.supertypes.forEach { e -> println(e) } val words = listOf("car", "forest", "Bible") println(words.map(String::length)) } ``` 在代码示例中,我们使用双冒号运算符创建对类和函数的引用。 ```kt val c = String::class c.supertypes.forEach { e -> println(e) } ``` 对于双冒号运算符,我们指的是`String`类。 我们打印其所有祖先。 ```kt val words = listOf("car", "forest", "Bible") println(words.map(String::length)) ``` 在这里,我们将`length()`函数应用于列表的所有单词。 ```kt kotlin.Comparable<kotlin.String> kotlin.CharSequence java.io.Serializable kotlin.Any [3, 6, 5] ``` 这是输出。 ## Kotlin 范围运算符 Kotlin 范围运算符(`..`)允许创建值范围。 `KotlinRanageOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { for (i in 1..14 step 3) { println(i) } } ``` 该示例使用范围运算符在`for`循环中创建整数序列。 ```kt 1 4 7 10 13 ``` 这是输出。 ## 非空断言运算符 非`null`断言运算符(`!!`)会将任何值转换为非`null`类型,并且如果该值为`null`则引发异常。 `KotlinNullAssertionOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { // val words = listOf("forest", null, "Bible", "sky") val words = listOf("forest", "Bible", "sky") var nOfChars: Int = 0 for (word in words) { val n = word!!.length nOfChars += n } println("There are ${nOfChars} characters in the list") } ``` 该示例计算单词列表中的字符数。 如果列表包含空值,则抛出`KotlinNullPointerException`。 ## Kotlin Elvis 运算符 Elvis 运算符?:如果不为 null,则返回其第一个表达式,否则返回第二个表达式。 `KotlinElvisOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val words = listOf("forest", null, "Bible", "sky") for (word in words) { val n = word?.length ?: 0 println("${word} has ${n} letters") } } ``` 在示例中,我们使用 Elvis 运算符检查列表中的空值。 ```kt val n = word?.length ?: 0 ``` 如果变量`word`包含 null,则?:返回 0。 ```kt forest has 6 letters null has 0 letters Bible has 5 letters sky has 3 letters ``` 这是输出。 ## Kotlin 空安全运算符 Kotlin 的`null`安全操作符`?.`提供了安全的方法调用-仅当对象不为`null`时才调用方法。 `KotlinNullSafetyOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val words = listOf("forest", null, "Bible", "sky") for (word in words) { println(word?.toUpperCase()) } ``` 在示例中,我们将字符串转换为大写; 我们使用`null`安全运算符。 对于`null`值,不调用该方法。 ```kt FOREST null BIBLE SKY ``` 这是输出。 ## Kotlin 索引访问运算符 Kotlin 索引访问运算符用于从数组获取值。 `KotlinIndexAccessOperatorEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val nums = arrayOf(3, 2, 1, 4, 5, 6, 7) val v1 = nums[0] val v2 = nums[3] println(v1) println(v2) } ``` 在示例中,我们使用`[]`运算符从数组中检索两个值。 ## Kotlin 引用相等运算符 Kotlin 区分结构相等和引用相等。 结构相等运算符(`==`)检查两个对象是否具有相同的内容。 引用相等运算符(`===`)检查变量是否指向内存中的同一对象。 `KotlinreferentialEqualityOperatorEx.kt` ```kt package com.zetcode data class Item(var name: String, var color: String) fun main(args: Array<String>) { val i1 = Item("coin", "brown") val i2 = i1 println("Output: ${i1 == i2}") println("Output: ${i1 === i2}") val i3 = Item("coin", "brown") val i4 = Item("coin", "brown") println("Output: ${i3 == i4}") println("Output: ${i3 === i4}") } ``` 该示例演示了`==`和`===`运算符之间的区别。 ```kt Output: true Output: true Output: true Output: false ``` 这是输出。 ## Kotlin 运算符优先级 运算符优先级告诉我们首先评估哪个运算符。 优先级对于避免表达式中的歧义是必要的。 以下表达式 28 或 40 的结果是什么? ```kt 3 + 5 * 5 ``` 像数学中一样,乘法运算符的优先级高于加法运算符。 结果是 28。 ```kt (3 + 5) * 5 ``` 要更改评估的顺序,可以使用括号。 括号内的表达式始终首先被求值。 上面的表达式的结果是 40。 `KotlinOperatorPrecedenceEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { println(3 + 5 * 5) println((3 + 5) * 5) println(!true or true) println(!(true or true)) } ``` 在此代码示例中,我们显示一些表达式。 每个表达式的结果取决于优先级。 ```kt println(3 + 5 * 5) ``` 该行打印 28。乘法运算符的优先级高于加法。 首先,计算`5 * 5`的乘积,然后加 3。 ```kt println((3 + 5) * 5) ``` 可以通过使用方括号来更改表达式的求值。 在这种情况下,将评估`3 + 5`,然后将该值乘以 5。此行显示 40。 ```kt println(!true or true) ``` 在这种情况下,求反运算符的优先级高于按位或。 首先,将初始`true`值取反为`false`,然后`|`运算符将`false`和`true`组合在一起,最后给出`true`。 ```kt 28 40 true false ``` 这是示例输出。 ## 关联规则 有时,优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性决定了具有相同优先级的运算符的评估顺序。 ```kt 9 / 3 * 3 ``` 此表达式的结果是 9 还是 1? 乘法,删除和模运算符从左到右关联。 因此,该表达式的计算方式为:`(9 / 3) * 3`,结果为 9。 算术运算符,布尔运算符和关系运算符从左到右关联。 三元运算符,递增,递减,一元正负,取反,按位不,类型强制转换,对象创建运算符从右到左关联。 `KotlinAssociativityRuleEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { var j = 0 j *= 3 + 1 println(j) } ``` 在示例中,我们的关联规则确定表达式的结果。 ```kt var j = 0 j *= 3 + 1 ``` 增强的赋值运算符从右到左关联。 我们可能期望结果为 1。但是实际结果为 0。由于有关联性。 首先评估右边的表达式,然后应用复合赋值运算符。 ## 计算素数 在下面的示例中,我们将计算素数。 `KotlinPrimeNumbersEx.kt` ```kt package com.zetcode fun main(args: Array<String>) { val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28) print("Prime numbers: ") for (num in nums) { if (num == 0 || num == 1) { continue } if (num == 2 || num == 3) { print(num.toString() + " ") continue } var i = Math.sqrt(num.toDouble()).toInt() var isPrime = true while (i > 1) { if (num % i == 0) { isPrime = false } i-- } if (isPrime) { print(num.toString() + " ") } } print('\n') } ``` 在上面的示例中,我们处理了几个运算符。 质数(或质数)是一个自然数,它具有两个截然不同的自然数除数:1 和它本身。 我们选择一个数字并将其除以 1 到所选数字的数字。 实际上,我们不必尝试所有较小的数字。 我们可以将数字除以所选数字的平方根。 该公式将起作用。 我们使用余数除法运算符。 ```kt val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28) ``` 我们将从这些数字计算素数。 ```kt if (num == 0 || num == 1) { continue } ``` 值 0 和 1 不被视为素数。 ```kt if (num == 2 || num == 3) { print(num.toString() + " ") continue } ``` 我们跳过 2 和 3 的计算。它们是质数。 请注意等式和条件或运算符的用法。 `==`的优先级高于`||`运算符。 因此,我们不需要使用括号。 ```kt var i = Math.sqrt(num.toDouble()).toInt() ``` 如果我们仅尝试小于所讨论数字的平方根的数字,那么我们可以。 ```kt while (i > 1) { ... i--; } ``` 这是一个`while`循环。 `i`是计算出的数字的平方根。 我们使用减量运算符将每个循环周期的`i`减 1。 当`i`小于 1 时,我们终止循环。 例如,我们有 9。9 的平方根是 3。我们将 9 的数字除以 3 和 2。这对于我们的计算就足够了。 ```kt if (num % i == 0) { isPrime = false } ``` 如果余数除法运算符针对任何`i`值返回 0,则说明该数字不是质数。 在本教程中,我们介绍了 Kotlin 运算符。 您可能也对相关教程感兴趣: [Kotlin 列表教程](/kotlin/lists/), [Kotlin 变量教程](/kotlin/variables/), [Kotlin 字符串教程](/kotlin/strings/), [Kotlin 控制流教程](/kotlin/controlflow/) 和 [Kotlin 数组教程](/kotlin/arrays/)。