Kotlin 變數宣告:val 與 var

在 Kotlin 中,宣告變數主要使用兩個關鍵字:valvar。 這體現了 Kotlin 對於 不可變性 (Immutability) 的重視。

變數宣告語法

標準的變數宣告語法如下:

關鍵字 變數名稱: 型別 = 初始值
  • 關鍵字valvar
  • 變數名稱:遵循 CamelCase (小駝峰) 命名法,例如 userName, isCompleted
  • 型別 (可選):如果可以從初始值推斷,可以省略。
  • 初始值:如果不馬上賦值,則必須明確指定型別。

val (唯讀變數)

val 代表 Value (或是常數),全名是 read-only local variable。 一旦指派了初始值,就 不能再修改 (Reassign)。這等同於 Java 的 final 變數。

val name = "Miko"
// name = "Jason"  // 錯誤!val 不能重新賦值

為什麼要優先使用 val?

  1. 可預測性:你永遠知道 val 變數的值不會在其他地方被偷偷改掉。
  2. 執行緒安全 (Thread Safety):在多執行緒環境下,不可變的資料是安全的,不需要複雜的同步機制。
  3. 函數式編程精神:鼓勵使用不可變資料,減少副作用 (Side Effects)。

編譯時期常數 (const val)

如果你需要定義一個全域的、編譯時期就確定的常數,可以使用 const val。 它通常放在檔案的最上層 (Top Level) 或 Object 中。

const val PI = 3.14159
const val APP_NAME = "MyApp"

注意:val 可以是在執行時期計算出來的值 (val time = System.currentTimeMillis()),但 const val 必須在編譯時就確定 (String 或 Primitive Type)。

除非真的需要修改變數的值,否則請預設使用 val。這能讓程式碼更安全、更容易維護。

var (可變變數)

var 代表 Variable。 你可以隨時修改它的值(但不能改變型別)。

var age = 18
age = 19  // 合法
// age = "20" // 錯誤!型別不符 (整數不能變字串)

型別推斷 (Type Inference)

你有注意到上面的例子沒有寫型別嗎? Kotlin 非常聰明,它會根據你給的初始值,自動推斷出變數的型別。

val name = "Miko" // 自動推斷為 String
val age = 18      // 自動推斷為 Int

如果你想顯式宣告型別,可以用冒號 : 加上型別名稱:

val name: String = "Miko"
val age: Int = 18

延遲初始化

有時候我們不想要 (或無法) 在宣告變數時馬上給初始值。這裡有兩種常見的做法:

lateinit var

有些時候我們無法在宣告時馬上給初始值 (例如在 Android 的 onCreate 中才要初始化 View)。 這時可以使用 lateinit var (Late Initialization)。

lateinit var message: String

fun init() {
    message = "Hello"
}

注意:

  • 只能用於 var
  • 不能用於 Primitive Types (Int, Double, Boolean...)。
  • 在存取前必須確保已經初始化,否則會噴 UninitializedPropertyAccessException

by lazy (惰性初始化)

如果你使用的是 val,並且希望在 第一次存取時 才計算初始值 (適合初始化很耗資源的物件),可以使用 by lazy

// 只有當第一次用到 database 時,大括號內的程式碼才會執行
val database: Database by lazy {
    println("Connecting to DB...")
    Database.connect()
}

fun main() {
     println("App Start")
     // 這裡才會印出 "Connecting to DB..."
     println(database.isConnected) 
}
  • 只能用於 val
  • 預設是 執行緒安全 (Thread Safe) 的。