Kotlin 運算子與運算表達式 (Operators)
運算子 (Operators) 是程式語言中用來對變數或數值進行操作的符號。例如 + 是加法運算子,* 是乘法運算子。
Kotlin 支援豐富的運算子,包括常見的算術運算、邏輯運算,以及 Kotlin 特有的範圍運算子和空值安全運算子。本章節將帶你詳細了解這些運算子的用法。
a + b 在底層其實是呼叫了 a.plus(b)。這稱為運算子重載 (Operator Overloading)。算術運算子 (Arithmetic Operators)
用於執行基本的數學運算。
| 運算子 | 說明 | 程式範例 | 對應函式 |
|---|---|---|---|
+ | 加法 | 10 + 5 (結果 15) | plus() |
- | 減法 | 10 - 5 (結果 5) | minus() |
* | 乘法 | 10 * 5 (結果 50) | times() |
/ | 除法 | 10 / 5 (結果 2) | div() |
% | 取餘數 (Modulus) | 10 % 3 (結果 1) | rem() |
fun main() {
val a = 10
val b = 3
println(a + b) // 13
println(a - b) // 7
println(a * b) // 30
// 注意:整數除法會無條件捨去小數點
println(a / b) // 3 (不是 3.333...)
println(a % b) // 1 (10 除以 3 的餘數)
}
Double 或 Float)。例如:10.0 / 3 結果會是 3.3333333333333335。指派運算子 (Assignment Operators)
用於將值賦予給變數,通常結合了算術運算。
| 運算子 | 說明 | 範例 | 等同於 |
|---|---|---|---|
= | 賦值 | x = 5 | x = 5 |
+= | 加後賦值 | x += 5 | x = x + 5 |
-= | 減後賦值 | x -= 5 | x = x - 5 |
*= | 乘後賦值 | x *= 5 | x = x * 5 |
/= | 除後賦值 | x /= 5 | x = x / 5 |
%= | 取餘數後賦值 | x %= 5 | x = x % 5 |
fun main() {
var num = 10
num += 5 // num 變為 15
num *= 2 // num 變為 30
println(num)
}
一元運算子 (Unary Operators)
只需要一個運算元的操作。
| 運算子 | 說明 | 範例 | 對應函式 |
|---|---|---|---|
+ | 正號 (通常省略) | +5 | unaryPlus() |
- | 負號 (變號) | -5 | unaryMinus() |
++ | 遞增 | ++a 或 a++ | inc() |
-- | 遞減 | --a 或 a-- | dec() |
! | 邏輯「非」 (Not) | !flag | not() |
遞增與遞減 (Prefix vs Postfix)
++ 和 -- 放在變數前面 (Prefix) 和後面 (Postfix) 有重要的差別:
- 前綴 (
++a):先將a加 1,然後回傳加完後的值。 - 後綴 (
a++):先回傳a原本的值,然後才將a加 1。
fun main() {
var a = 5
var b = 5
println(++a) // 輸出 6 (先加 1,再印出)
println(b++) // 輸出 5 (先印出原本的 5,再加 1)
println(a) // 6
println(b) // 6 (此時 b 已經變成 6 了)
}
比較運算子 (Comparison Operators)
用於比較兩個值,結果永遠是 Boolean (true 或 false)。
| 運算子 | 說明 |
|---|---|
== | 相等 (Structural Equality) |
!= | 不相等 |
< | 小於 |
> | 大於 |
<= | 小於等於 |
>= | 大於等於 |
相等性比較:== vs ===
Kotlin 有兩種相等的概念:
結構相等 (Structural Equality)
==: 檢查兩個物件的內容是否相同 (底層呼叫equals())。這是我們最常用的比較方式。參考相等 (Referential Equality)
===: 檢查兩個變數是否指向記憶體中的同一個物件。
fun main() {
val str1 = "Hello"
val str2 = "Hello"
val str3 = str1
// String 若內容相同,編譯器通常會優化指向同一記憶體,但為了演示 New 一個
val obj1 = Integer(100)
val obj2 = Integer(100)
println(obj1 == obj2) // true (數值內容都是 100)
println(obj1 === obj2) // false (它們是兩個不同的物件實體)
println(obj1 != obj2) // false
println(obj1 !== obj2) // true
}
邏輯運算子 (Logical Operators)
用於布林值 (Boolean) 的邏輯判斷。
| 運算子 | 說明 | 邏輯 |
|---|---|---|
&& | 且 (AND) | 兩邊都為 true 時,結果才為 true |
|| | 或 (OR) | 只要有一邊為 true,結果就為 true |
! | 非 (NOT) | true 變 false,false 變 true |
短路求值 (Short-circuit evaluation)
- 對於
&&:如果左邊為false,則不用計算右邊,結果一定為false。 - 對於
||:如果左邊為true,則不用計算右邊,結果一定為true。
這在檢查 null 或避免錯誤時很有用:
fun main() {
val str: String? = null
// 因為 str != null 為 false,後面的 str.length > 0 根本不會執行
// 這樣就避免了對 null 呼叫 .length 導致的 Crash
if (str != null && str.length > 0) {
println("String is valid")
} else {
println("String is null or empty")
}
}
位元運算子 (Bitwise Operations)
Kotlin 沒有像 C 或 Java 那樣的 <<, >>, &, | 符號運算子,而是使用中綴函式 (Infix Functions) 來處理位元運算。只有 Int 和 Long 可以進行位元運算。
| 函式 | 對應符號 (其他語言) | 說明 |
|---|---|---|
shl(bits) | << | 左移 (Signed shift left) |
shr(bits) | >> | 右移 (Signed shift right) |
ushr(bits) | >>> | 無號右移 (Unsigned shift right) |
and(bits) | & | 位元 And |
or(bits) | | | 位元 Or |
xor(bits) | ^ | 位元 Xor (互斥或) |
inv() | ~ | 位元反轉 (Invert) |
fun main() {
val x = 0b0101 // 十進位 5
val y = 0b0011 // 十進位 3
println(x and y) // 0b0001 (1)
println(x or y) // 0b0111 (7)
println(x xor y) // 0b0110 (6)
val z = 1
println(z shl 2) // 4 (二進位 1 變為 100)
}
範圍與檢查運算子 (Range & Check)
Kotlin 提供了一些特殊的運算子來處理範圍和型別檢查。
| 運算子 | 說明 | 範例 |
|---|---|---|
.. | 建立範圍 (Range) | 1..10 (1 到 10) |
in | 檢查是否在範圍內 | x in 1..10 |
!in | 檢查是否不在範圍內 | x !in 1..10 |
fun main() {
val item = 5
if (item in 1..10) {
println("$item 在 1 到 10 之間")
}
// 也可以用於集合
val list = listOf("A", "B", "C")
if ("A" in list) {
println("A 在清單中")
}
}
另外還有 is 和 !is 用於檢查型別,詳細請參考 型別檢查與轉型。
索引存取運算子 (Indexed Access Operator)
使用常看到的方括號 [] 來存取陣列或 Map 的元素。這其實對應到 get() 和 set() 函式。
a[i]等同於a.get(i)a[i] = b等同於a.set(i, b)
fun main() {
val array = arrayOf(1, 2, 3)
// 讀取
println(array[0]) // 1
// 寫入
array[0] = 100
println(array[0]) // 100
val map = mutableMapOf("name" to "Mike", "age" to "18")
map["name"] = "John" // 更新 Map
println(map["name"])
}
其他重要運算子
還有一些 Kotlin 特有的運算子,會在其專屬章節詳細介紹:
- 空值安全運算子 (
?.,?:,!!):請參考 Null Safety。 - 類別相關 (
::):用於 Reflection 或 Function Reference。
運算子優先順序 (Precedence)
Kotlin 的運算子優先順序與大多數 C-style 語言 (Java, C++, JavaScript) 類似。 大原則是:
*,/,%優先於+,-&&優先於||
如果不確定順序,或者為了讓程式碼更易讀,建議永遠使用括號 () 來明確指定運算順序。
val result = (10 + 5) * 2 // 明確先做加法,結果 30
val result2 = 10 + 5 * 2 // 先做乘法,結果 20