所有值都有類型
在 Scala 中,所有值都有類型,包括數字值和函式。下方的圖表說明了類型階層的子集。
Scala 類型階層
Any
是所有類型的超類型,也稱為頂層類型。它定義了某些通用方法,例如 equals
、hashCode
和 toString
。
頂層類型 Any
有子類型 Matchable
,用於標記我們可以執行模式比對的所有類型。保證屬性呼叫「參數性」非常重要。我們在此不深入探討,但總而言之,表示我們無法對類型為 Any
的值進行模式比對,只能對 Matchable
的子類型的值進行模式比對。 參考文件 包含有關 Matchable
的更多資訊。
Matchable
有兩個重要的子類型:AnyVal
和 AnyRef
。
AnyVal
代表值類型。有幾個預定義的值類型,而且它們不可為空:Double
、Float
、Long
、Int
、Short
、Byte
、Char
、Unit
和 Boolean
。 Unit
是一種不帶有有意義資訊的值類型。Unit
有一個實例,我們可以稱之為:()
。
AnyRef
代表參考類型。所有非值類型都被定義為參考類型。Scala 中的每個使用者定義類型都是 AnyRef
的子類型。如果 Scala 用於 Java 執行時間環境中,AnyRef
對應於 java.lang.Object
。
在基於語句的語言中,void
用於不傳回任何內容的方法。如果你在 Scala 中撰寫沒有傳回值的方法,例如以下方法,Unit
用於相同目的
def printIt(a: Any): Unit = println(a)
以下範例說明字串、整數、字元、布林值和函式都是 Any
的實例,而且可以像其他物件一樣處理
val list: List[Any] = List(
"a string",
732, // an integer
'c', // a character
'\'', // a character with a backslash escape
true, // a boolean value
() => "an anonymous function returning a string"
)
list.foreach(element => println(element))
此程式碼定義一個 List[Any]
類型的值 list
。此清單初始化為各種類型的元素,但每個元素都是 scala.Any
的實例,所以我們可以將它們新增到清單中。
以下是程式的輸出
a string
732
c
'
true
<function>
Scala 的「值類型」
如上所示,Scala 的數字類型延伸 AnyVal
,而且它們都是完整的物件。這些範例說明如何宣告這些數字類型的變數
val b: Byte = 1
val i: Int = 1
val l: Long = 1
val s: Short = 1
val d: Double = 2.0
val f: Float = 3.0
在頭四個範例中,如果你沒有明確指定類型,數字 1
預設為 Int
,因此如果你想要其他資料類型(Byte
、Long
或 Short
),你需要明確宣告這些類型,如下所示。帶有小數點的數字(例如 2.0)預設為 Double
,因此如果你想要 Float
,你需要宣告 Float
,如下一個範例所示。
由於 Int
和 Double
是預設數字類型,你通常會在沒有明確宣告資料類型的情況下建立它們。
val i = 123 // defaults to Int
val x = 1.0 // defaults to Double
在你的程式碼中,你也可以附加字元 L
、D
和 F
(及其小寫等效字元)到數字,以指定它們是 Long
、Double
或 Float
值。
val x = 1_000L // val x: Long = 1000
val y = 2.2D // val y: Double = 2.2
val z = -3.3F // val z: Float = -3.3
你也可以使用十六進位表示法來格式化整數(通常是 Int
,但也可以支援 L
字尾,以指定它們是 Long
)。
val a = 0xACE // val a: Int = 2766
val b = 0xfd_3aL // val b: Long = 64826
Scala 支援許多不同的方式來格式化相同的浮點數,例如:
val q = .25 // val q: Double = 0.25
val r = 2.5e-1 // val r: Double = 0.25
val s = .0025e2F // val s: Float = 0.25
Scala 也有 String
和 Char
類型,你通常可以使用隱含形式來宣告它們。
val s = "Bill"
val c = 'a'
如所示,用雙引號將字串括起來(或用三引號表示多行字串),並用單引號將字元括起來。
這些資料類型及其範圍如下:
資料類型 | 可能值 |
---|---|
布林 | true 或 false |
位元組 | 8 位元有號二補數整數(-2^7 至 2^7-1,包含) -128 至 127 |
短整數 | 16 位元有號二補數整數(-2^15 至 2^15-1,包含) -32,768 至 32,767 |
整數 | 32 位元二補數整數(-2^31 至 2^31-1,包含) -2,147,483,648 至 2,147,483,647 |
長整數 | 64 位元二補數整數(-2^63 至 2^63-1,包含) (-2^63 到 2^63-1,包含) |
浮點數 | 32 位元 IEEE 754 單精度浮點數 1.40129846432481707e-45 到 3.40282346638528860e+38 |
雙精度浮點數 | 64 位元 IEEE 754 雙精度浮點數 4.94065645841246544e-324 到 1.79769313486231570e+308 |
字元 | 16 位元無符號 Unicode 字元 (0 到 2^16-1,包含) 0 到 65,535 |
字串 | Char 的序列 |
字串
Scala 字串類似於 Java 字串,但與 Java 不同(至少在 Java 15 之前),使用三個引號可以輕鬆建立多行字串
val quote = """The essence of Scala:
Fusion of functional and object-oriented
programming in a typed setting."""
這種基本方法的一個缺點是,第一行之後的行會縮排,如下所示
"The essence of Scala:
Fusion of functional and object-oriented
programming in a typed setting."
如果間距很重要,請在第一行之後的所有行前面加上 |
符號,並在字串之後呼叫 stripMargin
方法
val quote = """The essence of Scala:
|Fusion of functional and object-oriented
|programming in a typed setting.""".stripMargin
現在所有行都在字串內靠左對齊
"The essence of Scala:
Fusion of functional and object-oriented
programming in a typed setting."
Scala 字串還支援強大的字串內插方法,我們將在 下一章 中討論。
BigInt
和 BigDecimal
當您需要非常大的數字時,請使用 BigInt
和 BigDecimal
類型
val a = BigInt(1_234_567_890_987_654_321L)
val b = BigDecimal(123_456.789)
其中 Double
和 Float
是近似十進位數,BigDecimal
用於精確運算,例如處理貨幣時。
BigInt
和 BigDecimal
的一個優點是,它們支援您習慣於使用數字類型的所有運算子
val b = BigInt(1234567890) // scala.math.BigInt = 1234567890
val c = b + b // scala.math.BigInt = 2469135780
val d = b * b // scala.math.BigInt = 1524157875019052100
類型轉換
例如
val b: Byte = 127
val i: Int = b // 127
val face: Char = '☺'
val number: Int = face // 9786
只有在沒有資訊遺失的情況下,您才能轉換為某個類型。否則,您需要明確說明轉換
val x: Long = 987654321
val y: Float = x.toFloat // 9.8765434E8 (note that `.toFloat` is required because the cast results in precision loss)
val z: Long = y // Error
您也可以將參考類型轉換為子類型。這將在後面的導覽中介紹。
Nothing
和 null
Nothing
是所有類型的子類型,也稱為底部類型。沒有任何值具有類型 Nothing
。常見的用途是表示非終止,例如引發的例外、程式結束或無限迴圈,也就是說,它是沒有評估為值的運算式類型,或是不正常返回的方法。
Null
是所有參考類型的子類型(也就是 AnyRef
的任何子類型)。它有一個由關鍵字字面值 null
識別的單一值。目前,使用 null
被認為是不良習慣。它應該主要用於與其他 JVM 語言的互通性。一個選擇加入的編譯器選項會變更 Null
的狀態,以修正與其使用相關的警告。此選項可能會在未來的 Scala 版本中成為預設值。您可以 在此進一步了解它。
在此同時,幾乎不應該在 Scala 程式碼中使用 null
。替代 null
的方法會在本手冊的 函式程式設計章節 和 API 文件 中討論。