ZetCode

Kotlin 运算符

最后修改于 2024 年 1 月 29 日

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

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

表达式由操作数和运算符构成。 表达式的运算符指示要对操作数应用哪些操作。 表达式中运算符的求值顺序由运算符的优先级结合性决定。

一个运算符通常有一个或两个操作数。 那些只使用一个操作符的操作符被称为一元运算符。 那些使用两个操作数的被称为二元运算符

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

Kotlin 符号运算符

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

sign_operators.kt
package com.zetcode

fun main() {

    println(2)
    println(+2)
    println(-2)
}

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

minus_sign.kt
package com.zetcode

fun main() {

    val a = 1

    println(-a)
    println(-(-a))
}

减号会改变值的符号。

Kotlin 赋值运算符

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

val x = 1

在这里,我们将一个数字赋给 x 变量。

x = x + 1

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

3 = x

此代码行导致语法错误。 我们不能将值赋给字面量。

Kotlin 增强赋值运算符

增强赋值运算符是包含两个运算符的简写运算符。 增强赋值运算符在其他编程语言中也称为复合赋值运算符。

a = a + 3
a += 3

+= 复合运算符是这些简写运算符之一。上面的两个表达式是相等的。将值 3 加到 a 变量上。

Kotlin 增强赋值运算符是

+=  -=   *=   /=   %=

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

augmented_assignment_operators.kt
package com.zetcode

fun main() {

    var a = 1
    a = a + 1

    println(a)

    a += 5
    println(a)

    a *= 3
    println(a)
}

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

var a = 1
a = a + 1

a 变量初始化为 1。 使用非简写符号将值 1 添加到变量中。

a += 5

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

a *= 3

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

2
7
21

Kotlin 连接字符串

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

concatenate_strings.kt
package com.zetcode

fun main() {

    println("Return " + "of " + "the king.")
    println("Return".plus(" of").plus(" the king."))
}

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

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

字符串与 + 运算符连接。

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

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

Kotlin 递增和递减运算符

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

x++
x = x + 1
...
y--
y = y - 1

以上两对表达式执行相同的操作。

inc_dec.kt
package com.zetcode

fun main() {

    var x = 6

    x++
    x++

    println(x)

    x--
    println(x)
}

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

int x = 6

x++
x++

我们将 x 变量初始化为 6。然后我们对 x 加一两次。现在变量的值是 8。

x--

我们使用了递减运算符。现在变量的值是 7。

Kotlin 算术运算符

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

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

下面的示例展示了算术运算。

arithmetic_operators.kt
package com.zetcode

fun main() {

    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)
}

在前面的示例中,我们使用了加法、减法、乘法、除法和取余运算。这些都与数学中的一样熟悉。

val rem = c % a

% 运算符称为余数或模运算符。它用于找出两个数相除的余数。例如,9 % 4,9 模 4 等于 1,因为 4 能整除 9 两次,余数为 1。

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

division_operator.kt
package com.zetcode

fun main() {

    val c = 5 / 2
    println(c)

    val d = 5 / 2.0
    println(d)
}

在前面的示例中,我们对两个数进行了除法运算。

val c = 5 / 2

在这段代码中,我们进行了整数除法。除法运算的返回值是整数。当我们对两个整数进行除法时,结果是一个整数。

val d = 5 / 2.0

如果其中一个值是双精度浮点数或单精度浮点数,我们就执行浮点数除法。在本例中,第二个操作数是双精度浮点数,所以结果也是双精度浮点数。

2
2.5

我们看到了程序的输出。

Kotlin 布尔运算符

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

符号名称
&&逻辑与
||逻辑或
!逻辑非

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

boolean_exp.kt
package com.zetcode

fun main() {

    val x = 3
    val y = 8

    println(x == y)
    println(y > x)

    if (y > x) {

        println("y is greater than x")
    }
}

许多表达式会产生布尔值。例如,布尔值用于条件语句。

println(x == y)
println(y > x)

关系运算符始终产生布尔值。这两行打印 false 和 true。

if (y > x) {

    println("y is greater than x")
}

只有当括号内的条件满足时,才会执行 if 语句的主体。y > x 返回 true,因此消息 "y is greater than x" 会打印到终端。

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

and_operator.kt
package com.zetcode

fun main() {

    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。

true
false
false
false

只有一个表达式的结果为 true。

如果任何一个操作数为真,逻辑或 (||) 运算符的计算结果为真。

or_operator.kt
package com.zetcode

fun main() {

    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。

true
true
true
false

四分之三的表达式结果为 true。

否定运算符 ! 将 true 变为 false,将 false 变为 true。

negation_operator.kt
package com.zetcode

fun main() {

    println(! true)
    println(! false)
    println(! (4 < 3))
}

该示例展示了否定运算符的实际应用。

false
true
true

Kotlin 比较运算符

比较运算符用于比较值。 这些运算符始终产生布尔值。

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

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

comparison_operators.kt
package com.zetcode

fun main() {

    println(3 < 4);
    println(3 == 4);
    println(4 >= 3);
    println(4 != 3);
}

在代码示例中,我们有四个表达式。 这些表达式比较整数值。 每个表达式的结果是真或假。 在 Kotlin 中,我们使用 == 来比较数字。 (一些语言(如 Ada、Visual Basic 或 Pascal)使用 = 来比较数字。)

Kotlin 位运算

与 Java 不同,Kotlin 中没有位运算符。 Kotlin 有执行位运算的命名函数。

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

位与运算在两个数字之间执行逐位比较。 只有当操作数中对应的位都为 1 时,位位置的结果才为 1。

      00110
   &  00011
   =  00010

第一个数字是 6 的二进制表示法,第二个是 3,结果是 2。

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

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

     00110
   | 00011
   = 00111

结果是 00110 或十进制的 7。

println(6 or 3) // prints 7
println(3 or 6) // prints 7

Kotlin is 运算符

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

is_operator.kt
package com.zetcode

open class Base
class Derived : Base()

fun main() {

    val b = Base()
    val d = Derived()

    println(d is Base)
    println(b is Derived)
    println(d is Any)
}

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

println(d is Base)

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

println(b is Derived)

b 对象不是 Derived 类的实例。 此行打印 false。

println(d is Any)

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

true
false
true

Kotlin lambda 运算符

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

lambda_operator.kt
package com.zetcode

import java.util.Arrays

fun main() {

    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 表达式进行排序。

[atom, blue, car, kind, massive]

Kotlin 双冒号运算符

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

double_colon_operator.kt
package com.zetcode

fun main() {

    val c = String::class

    c.supertypes.forEach { e -> println(e) }

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

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

val c = String::class

c.supertypes.forEach { e -> println(e) }

使用双冒号运算符,我们引用 String 类。 我们打印它的所有祖先。

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

在这里,我们对列表中的所有单词应用 length 函数。

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

Kotlin 范围运算符

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

range_operator.kt
package com.zetcode

fun main() {

    for (i in 1..14 step 3) {

        println(i)
    }
}

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

1
4
7
10
13

非空断言运算符

非空断言运算符 (!!) 将任何值转换为非空类型,如果该值为 null,则抛出异常。

nonnull_assertion_operator.kt
package com.zetcode

fun main() {

//    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,则返回第一个表达式,否则返回第二个表达式。

elvis_operator.kt
package com.zetcode

fun main() {

    val words = listOf("forest", null, "Bible", "sky")

    for (word in words) {

        val n = word?.length ?: 0

        println("${word} has ${n} letters")
    }
}

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

val n = word?.length ?: 0

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

forest has 6 letters
null has 0 letters
Bible has 5 letters
sky has 3 letters

Kotlin 空安全运算符

Kotlin 的空安全运算符 ?. 提供了一个安全的方法调用——仅当对象不为 null 时才调用一个方法。

null_safety_operator.kt
package com.zetcode

fun main() {

    val words = listOf("forest", null, "Bible", "sky")

    for (word in words) {

        println(word?.toUpperCase())
}

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

FOREST
null
BIBLE
SKY

Kotlin 索引访问运算符

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

index_access_operator.kt
package com.zetcode

fun main() {

    val nums = arrayOf(3, 2, 1, 4, 5, 6, 7)

    val v1 = nums[0]
    val v2 = nums[3]

    println(v1)
    println(v2)
}

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

Kotlin 引用相等运算符

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

referential_equality_operator.kt
package com.zetcode

data class Item(var name: String, var color: String)

fun main() {

    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}")
}

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

Output: true
Output: true
Output: true
Output: false

Kotlin 运算符优先级

运算符优先级告诉我们哪些运算符首先被求值。优先级级别对于避免表达式中的歧义是必需的。

以下表达式的结果是 28 还是 40?

3 + 5 * 5

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

(3 + 5) * 5

要更改求值顺序,我们可以使用括号。括号内的表达式总是首先被求值。上述表达式的结果是 40。

operator_precedence.kt
package com.zetcode

fun main() {

    println(3 + 5 * 5)
    println((3 + 5) * 5)

    println(!true or true)
    println(!(true or true))
}

在这段代码示例中,我们展示了几个表达式。每个表达式的结果取决于优先级级别。

println(3 + 5 * 5)

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

println((3 + 5) * 5)

可以使用圆括号更改表达式的求值。 在这种情况下,3 + 5 被求值,然后该值乘以 5。 此行打印 40。

println(!true or true)

在这种情况下,否定运算符的优先级高于按位或。 首先,初始的真值被否定为假,然后 | 运算符将假和真组合起来,最后得到真。

28
40
true
false

结合性规则

有时优先级不足以确定表达式的结果。还有另一个规则称为结合性。运算符的结合性决定了具有相同优先级级别的运算符的求值顺序。

9 / 3 * 3

这个表达式的结果是 9 还是 1?乘法、除法和模运算符是从左到右结合的。所以表达式的求值方式是:(9 / 3) * 3 结果是 9。

算术、布尔和关系运算符是从左到右关联的。 三元运算符、递增、递减、一元加和减、否定、按位取反、类型转换、对象创建运算符是右到左关联的。

associativity_rule.kt
package com.zetcode

fun main() {

    var j = 0

    j *= 3 + 1

    println(j)
}

在这个例子中,我们用结合律规则确定表达式的结果。

var j = 0

j *= 3 + 1

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

计算质数

在下面的例子中,我们将计算质数。

prime_numbers.kt
package com.zetcode

fun main() {

    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 到所选数字的数字。 实际上,我们不必尝试所有较小的数字; 我们可以除以小于所选数字的平方根的数字。 公式将起作用。 我们使用余数除法运算符。

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)

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

if (num == 0 || num == 1) {
    continue
}

值 0 和 1 不被认为是素数。

if (num == 2 || num == 3) {

    print(num.toString() + " ")
    continue
}

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

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

如果我们只尝试小于目标数字的平方根的数字,那就可以了。

while (i > 1) {
    ...
    i--
}

这是一个 while 循环。 i 是该数字的计算平方根。 我们使用递减运算符将 i 减 1。 当 i 小于 1 时,我们终止循环。 例如,我们有数字 9。 9 的平方根是 3。 我们将 9 除以 3 和 2。 这足以满足我们的计算。

if (num % i == 0) {

    isPrime = false
}

如果求余运算符对于任何 i 值返回 0,则目标数字不是质数。

来源

Kotlin 关键字和运算符 - 语言参考

在本文中,我们介绍了 Kotlin 运算符。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出 所有 Kotlin 教程