原文: http://zetcode.com/kotlin/operators/

在本教程中,我们将介绍 Kotlin 运算符。 我们展示了如何使用运算符创建表达式。

运算符是特殊符号,表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。 操作数是运算符的输入(参数)之一。

表达式是根据操作数和运算符构造的。 表达式的运算符指示将哪些运算应用于操作数。 表达式中运算符的求值顺序由运算符的优先级和关联性确定。

一个运算符通常有一个或两个操作数。 那些仅使用一个操作数的运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。

某些运算符可以在不同的上下文中使用。 例如,+运算符可以在不同的情况下使用:它添加数字,连接字符串或指示数字的符号。 我们说运算符是重载。

Kotlin 标志运算符

有两个符号运算符:+-。 它们用于指示或更改值的符号。

KotlinSignOperatorsEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. println(2)
  4. println(+2)
  5. println(-2)
  6. }

+-符号指示值的符号。 加号可用于表示我们有一个正数。 可以省略它,并且在大多数情况下可以这样做。

KotlinMinusSignEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val a = 1
  4. println(-a)
  5. println(-(-a))
  6. }

减号更改值的符号。

Kotlin 赋值运算符

赋值运算符=将值赋给变量。 变量是值的占位符。 在数学中,=运算符具有不同的含义。 在等式中,=运算符是一个相等运算符。 等式的左边等于右边的等式。

  1. val x = 1

在这里,我们为x变量分配一个数字。

  1. x = x + 1

这个表达式在数学上没有意义,但是在编程中是合法的。 该表达式将x变量加 1。 右边等于 2,并且 2 分配给x

  1. 3 = x

此代码行导致语法错误。 我们无法为字面值分配值。

Kotlin 扩展赋值运算子

扩展赋值运算符是由两个运算符组成的速记运算符。 增强的赋值运算符在其他编程语言中也称为复合赋值运算符。

  1. a = a + 3
  2. a += 3

+=复合运算符是这些速记运算符之一。 以上两个表达式相等。 将值 3 添加到变量a中。

Kotlin 扩展分配运算符为:

  1. += -= *= /= %=

下面的示例使用两个复合运算符。

KotlinAugmentedAssignmentOperatorsEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. var a = 1
  4. a = a + 1
  5. println(a)
  6. a += 5
  7. println(a)
  8. a *= 3
  9. println(a)
  10. }

我们使用+=*=复合运算符。

  1. var a = 1
  2. a = a + 1

a变量被初始化为 1。 使用非速记符号将值 1 添加到变量。

  1. a += 5

使用+=复合运算符,将 5 加到a变量中。 该语句等于a = a + 5

  1. a *= 3

使用*=运算符,将a乘以 3。该语句等于a = a * 3

  1. 2
  2. 7
  3. 21

这是示例输出。

Kotlin 连接字符串

在 Kotlin 中,+运算符还用于连接字符串。

KotlinConcatenateStringsEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. println("Return " + "of " + "the king.")
  4. println("Return".plus(" of").plus(" the king."))
  5. }

我们将三个字符串连接在一起。

  1. println("Return " + "of " + "the king.")

字符串用+运算符连接。

  1. println("Return".plus(" of").plus(" the king."))

连接字符串的另一种方法是plus()方法。

Kotlin 增减运算符

将值递增或递减一个是编程中的常见任务。 Kotlin 为此有两个方便的运算符:++--

  1. x++
  2. x = x + 1
  3. ...
  4. y--
  5. y = y - 1

上面两对表达式的作用相同。

KotlinIncDecEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. var x = 6
  4. x++
  5. x++
  6. println(x)
  7. x--
  8. println(x)
  9. }

在上面的示例中,我们演示了两个运算符的用法。

  1. int x = 6
  2. x++
  3. x++

x变量初始化为 6。然后将x递增两次。 现在变量等于 8。

  1. x--

我们使用减量运算符。 现在变量等于 7。

Kotlin 算术运算符

下表是 Kotlin 中的算术运算符表。

符号 名称
+ 加法
- 减法
* 乘法
/ 乘法
% 余数

以下示例显示了算术运算。

KotlinArithmeticOperatorsEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val a = 10
  4. val b = 11
  5. val c = 12
  6. val add = a + b + c
  7. val sb = c - a
  8. val mult = a * b
  9. val div = c / 3
  10. val rem = c % a
  11. println(add)
  12. println(sb)
  13. println(mult)
  14. println(div)
  15. println(rem)
  16. }

在前面的示例中,我们使用加法,减法,乘法,除法和余数运算。 这些都是数学所熟悉的。

  1. val rem = c % a

%运算符称为余数或模运算符。 它找到一个数除以另一个的余数。 例如9 % 4,9 模 4 为 1,因为 4 两次进入 9 且余数为 1。

整数除法和浮点除法之间有区别。

KotlinDivisionEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val c = 5 / 2
  4. println(c)
  5. val d = 5 / 2.0
  6. println(d)
  7. }

在前面的示例中,我们将两个数字相除。

  1. val c = 5 / 2

在这段代码中,我们完成了整数除法。 除法运算的返回值为整数。 当我们将两个整数相除时,结果是一个整数。

  1. val d = 5 / 2.0

如果值之一是doublefloat,则执行浮点除法。 在我们的例子中,第二个操作数是双精度数,因此结果是双精度数。

  1. 2
  2. 2.5

我们看到了程序的结果。

Kotlin 布尔运算符

在 Kotlin 中,我们有三个逻辑运算符。

符号 名称
&& 逻辑与
` ` 逻辑或
! 否定

布尔运算符也称为逻辑运算符。

KotlinBooleanExpEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val x = 3
  4. val y = 8
  5. println(x == y)
  6. println(y > x)
  7. if (y > x) {
  8. println("y is greater than x")
  9. }
  10. }

许多表达式导致布尔值。 例如,在条件语句中使用布尔值。

  1. println(x == y)
  2. println(y > x)

关系运算符始终导致布尔值。 这两行分别显示falsetrue

  1. if (y > x) {
  2. println("y is greater than x")
  3. }

仅在满足括号内的条件时才执行if语句的主体。 y > x返回true,因此消息"y大于x"被打印到终端。

truefalse关键字表示 Kotlin 中的布尔字面值。

KotlinAndOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val a = true && true
  4. val b = true && false
  5. val c = false && true
  6. val d = false && false
  7. println(a)
  8. println(b)
  9. println(c)
  10. println(d)
  11. }

该代码示例显示了逻辑和(&&)运算符。 仅当两个操作数均为true时,它的评估结果为true

  1. true
  2. false
  3. false
  4. false

只有一个表达式可得出true

如果两个操作数中的任何一个为true,则逻辑或(||)运算符的计算结果为true

KotlinOrOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val a = true || true
  4. val b = true || false
  5. val c = false || true
  6. val d = false || false
  7. println(a)
  8. println(b)
  9. println(c)
  10. println(d)
  11. }

如果运算符的任一侧为真,则操作的结果为真。

  1. true
  2. true
  3. true
  4. false

四个表达式中的三个表示为true

否定运算符!true设为false,并将false设为false

KotlinNegationEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. println(! true)
  4. println(! false)
  5. println(! (4 < 3))
  6. }

该示例显示了否定运算符的作用。

  1. false
  2. true
  3. true

这是程序的输出。

Kotlin 比较运算符

比较运算符用于比较值。 这些运算符总是产生布尔值。

符号 含义
< 小于
<= 小于或等于
> 大于
>= 大于或等于
== 等于
!= 不等于

比较运算符也称为关系运算符。

KotlinComparisonOperatorsEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. println(3 < 4);
  4. println(3 == 4);
  5. println(4 >= 3);
  6. println(4 != 3);
  7. }

在代码示例中,我们有四个表达式。 这些表达式比较整数值。 每个表达式的结果为truefalse。 在 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() – 按位反转

这些函数仅适用于IntLong类型。

按位操作在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时,位位置的结果才为 1。

  1. 00110
  2. & 00011
  3. = 00010

第一个数字是二进制符号 6,第二个数字是 3,结果是 2。

  1. println(6 and 3) // prints 2
  2. println(3 and 6) // prints 2

按位或操作在两个数字之间进行逐位比较。 如果操作数中的任何对应位为 1,则位位置的结果为 1。

  1. 00110
  2. | 00011
  3. = 00111

结果为00110或十进制 7。

  1. println(6 or 3) // prints 7
  2. println(3 or 6) // prints 7

Kotlin is运算符

要在运行时检查对象是否符合给定类型,我们可以使用is运算符或其否定形式!is

KotlinIsOperatorEx.kt

  1. package com.zetcode
  2. open class Base
  3. class Derived : Base()
  4. fun main(args: Array<String>) {
  5. val b = Base()
  6. val d = Derived()
  7. println(d is Base)
  8. println(b is Derived)
  9. println(d is Any)
  10. }

在示例中,我们有两个类:一个基类和一个从基类派生的类。

  1. println(d is Base)

此行检查变量d是否指向作为Base类实例的类。 由于Derived类继承自Base类,因此它也是Base类的实例。 该行打印正确。

  1. println(b is Derived)

b对象不是Derived类的实例。 该行显示false

  1. println(d is Any)

每个类都有Any作为超类。 因此,d对象也是Any类的实例。

  1. true
  2. false
  3. true

这是程序的输出。

Kotlin Lambda 运算符

Kotlin 具有 lambda 运算符(->)。 它分隔了 lambda 表达式的参数和主体。

KotlinLambdaOperatorEx.kt

  1. package com.zetcode
  2. import java.util.Arrays
  3. fun main(args: Array<String>) {
  4. val words = arrayOf("kind", "massive", "atom", "car", "blue")
  5. Arrays.sort(words) { s1: String, s2: String -> s1.compareTo(s2) }
  6. println(Arrays.toString(words))
  7. }

在示例中,我们定义了一个字符串数组。 使用Arrays.sort()方法和 lambda 表达式对数组进行排序。

  1. [atom, blue, car, kind, massive]

这是输出。

Kotlin 双冒号运算符

双冒号运算符(::)用于创建类或函数引用。

KotlinDoubleColonOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val c = String::class
  4. c.supertypes.forEach { e -> println(e) }
  5. val words = listOf("car", "forest", "Bible")
  6. println(words.map(String::length))
  7. }

在代码示例中,我们使用双冒号运算符创建对类和函数的引用。

  1. val c = String::class
  2. c.supertypes.forEach { e -> println(e) }

对于双冒号运算符,我们指的是String类。 我们打印其所有祖先。

  1. val words = listOf("car", "forest", "Bible")
  2. println(words.map(String::length))

在这里,我们将length()函数应用于列表的所有单词。

  1. kotlin.Comparable<kotlin.String>
  2. kotlin.CharSequence
  3. java.io.Serializable
  4. kotlin.Any
  5. [3, 6, 5]

这是输出。

Kotlin 范围运算符

Kotlin 范围运算符(..)允许创建值范围。

KotlinRanageOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. for (i in 1..14 step 3) {
  4. println(i)
  5. }
  6. }

该示例使用范围运算符在for循环中创建整数序列。

  1. 1
  2. 4
  3. 7
  4. 10
  5. 13

这是输出。

非空断言运算符

null断言运算符(!!)会将任何值转换为非null类型,并且如果该值为null则引发异常。

KotlinNullAssertionOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. // val words = listOf("forest", null, "Bible", "sky")
  4. val words = listOf("forest", "Bible", "sky")
  5. var nOfChars: Int = 0
  6. for (word in words) {
  7. val n = word!!.length
  8. nOfChars += n
  9. }
  10. println("There are ${nOfChars} characters in the list")
  11. }

该示例计算单词列表中的字符数。 如果列表包含空值,则抛出KotlinNullPointerException

Kotlin Elvis 运算符

Elvis 运算符?:如果不为 null,则返回其第一个表达式,否则返回第二个表达式。

KotlinElvisOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val words = listOf("forest", null, "Bible", "sky")
  4. for (word in words) {
  5. val n = word?.length ?: 0
  6. println("${word} has ${n} letters")
  7. }
  8. }

在示例中,我们使用 Elvis 运算符检查列表中的空值。

  1. val n = word?.length ?: 0

如果变量word包含 null,则?:返回 0。

  1. forest has 6 letters
  2. null has 0 letters
  3. Bible has 5 letters
  4. sky has 3 letters

这是输出。

Kotlin 空安全运算符

Kotlin 的null安全操作符?.提供了安全的方法调用-仅当对象不为null时才调用方法。

KotlinNullSafetyOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val words = listOf("forest", null, "Bible", "sky")
  4. for (word in words) {
  5. println(word?.toUpperCase())
  6. }

在示例中,我们将字符串转换为大写; 我们使用null安全运算符。 对于null值,不调用该方法。

  1. FOREST
  2. null
  3. BIBLE
  4. SKY

这是输出。

Kotlin 索引访问运算符

Kotlin 索引访问运算符用于从数组获取值。

KotlinIndexAccessOperatorEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val nums = arrayOf(3, 2, 1, 4, 5, 6, 7)
  4. val v1 = nums[0]
  5. val v2 = nums[3]
  6. println(v1)
  7. println(v2)
  8. }

在示例中,我们使用[]运算符从数组中检索两个值。

Kotlin 引用相等运算符

Kotlin 区分结构相等和引用相等。 结构相等运算符(==)检查两个对象是否具有相同的内容。 引用相等运算符(===)检查变量是否指向内存中的同一对象。

KotlinreferentialEqualityOperatorEx.kt

  1. package com.zetcode
  2. data class Item(var name: String, var color: String)
  3. fun main(args: Array<String>) {
  4. val i1 = Item("coin", "brown")
  5. val i2 = i1
  6. println("Output: ${i1 == i2}")
  7. println("Output: ${i1 === i2}")
  8. val i3 = Item("coin", "brown")
  9. val i4 = Item("coin", "brown")
  10. println("Output: ${i3 == i4}")
  11. println("Output: ${i3 === i4}")
  12. }

该示例演示了=====运算符之间的区别。

  1. Output: true
  2. Output: true
  3. Output: true
  4. Output: false

这是输出。

Kotlin 运算符优先级

运算符优先级告诉我们首先评估哪个运算符。 优先级对于避免表达式中的歧义是必要的。

以下表达式 28 或 40 的结果是什么?

  1. 3 + 5 * 5

像数学中一样,乘法运算符的优先级高于加法运算符。 结果是 28。

  1. (3 + 5) * 5

要更改评估的顺序,可以使用括号。 括号内的表达式始终首先被求值。 上面的表达式的结果是 40。

KotlinOperatorPrecedenceEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. println(3 + 5 * 5)
  4. println((3 + 5) * 5)
  5. println(!true or true)
  6. println(!(true or true))
  7. }

在此代码示例中,我们显示一些表达式。 每个表达式的结果取决于优先级。

  1. println(3 + 5 * 5)

该行打印 28。乘法运算符的优先级高于加法。 首先,计算5 * 5的乘积,然后加 3。

  1. println((3 + 5) * 5)

可以通过使用方括号来更改表达式的求值。 在这种情况下,将评估3 + 5,然后将该值乘以 5。此行显示 40。

  1. println(!true or true)

在这种情况下,求反运算符的优先级高于按位或。 首先,将初始true值取反为false,然后|运算符将falsetrue组合在一起,最后给出true

  1. 28
  2. 40
  3. true
  4. false

这是示例输出。

关联规则

有时,优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性决定了具有相同优先级的运算符的评估顺序。

  1. 9 / 3 * 3

此表达式的结果是 9 还是 1? 乘法,删除和模运算符从左到右关联。 因此,该表达式的计算方式为:(9 / 3) * 3,结果为 9。

算术运算符,布尔运算符和关系运算符从左到右关联。 三元运算符,递增,递减,一元正负,取反,按位不,类型强制转换,对象创建运算符从右到左关联。

KotlinAssociativityRuleEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. var j = 0
  4. j *= 3 + 1
  5. println(j)
  6. }

在示例中,我们的关联规则确定表达式的结果。

  1. var j = 0
  2. j *= 3 + 1

增强的赋值运算符从右到左关联。 我们可能期望结果为 1。但是实际结果为 0。由于有关联性。 首先评估右边的表达式,然后应用复合赋值运算符。

计算素数

在下面的示例中,我们将计算素数。

KotlinPrimeNumbersEx.kt

  1. package com.zetcode
  2. fun main(args: Array<String>) {
  3. val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
  4. 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28)
  5. print("Prime numbers: ")
  6. for (num in nums) {
  7. if (num == 0 || num == 1) {
  8. continue
  9. }
  10. if (num == 2 || num == 3) {
  11. print(num.toString() + " ")
  12. continue
  13. }
  14. var i = Math.sqrt(num.toDouble()).toInt()
  15. var isPrime = true
  16. while (i > 1) {
  17. if (num % i == 0) {
  18. isPrime = false
  19. }
  20. i--
  21. }
  22. if (isPrime) {
  23. print(num.toString() + " ")
  24. }
  25. }
  26. print('\n')
  27. }

在上面的示例中,我们处理了几个运算符。 质数(或质数)是一个自然数,它具有两个截然不同的自然数除数:1 和它本身。 我们选择一个数字并将其除以 1 到所选数字的数字。 实际上,我们不必尝试所有较小的数字。 我们可以将数字除以所选数字的平方根。 该公式将起作用。 我们使用余数除法运算符。

  1. val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
  2. 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28)

我们将从这些数字计算素数。

  1. if (num == 0 || num == 1) {
  2. continue
  3. }

值 0 和 1 不被视为素数。

  1. if (num == 2 || num == 3) {
  2. print(num.toString() + " ")
  3. continue
  4. }

我们跳过 2 和 3 的计算。它们是质数。 请注意等式和条件或运算符的用法。 ==的优先级高于||运算符。 因此,我们不需要使用括号。

  1. var i = Math.sqrt(num.toDouble()).toInt()

如果我们仅尝试小于所讨论数字的平方根的数字,那么我们可以。

  1. while (i > 1) {
  2. ...
  3. i--;
  4. }

这是一个while循环。 i是计算出的数字的平方根。 我们使用减量运算符将每个循环周期的i减 1。 当i小于 1 时,我们终止循环。 例如,我们有 9。9 的平方根是 3。我们将 9 的数字除以 3 和 2。这对于我们的计算就足够了。

  1. if (num % i == 0) {
  2. isPrime = false
  3. }

如果余数除法运算符针对任何i值返回 0,则说明该数字不是质数。

在本教程中,我们介绍了 Kotlin 运算符。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin 变量教程Kotlin 字符串教程Kotlin 控制流教程Kotlin 数组教程