Scala的基本類型及文本化
Scala的基本類型
表格5.1顯示了Scala的許多基本的類型和其實例值域范圍。總體來說,類型Byte,Short,Int,Long和Char被稱為整數類型:integral type。整數類型加上Float和Double被稱為數類型:numeric type。
51CTO編輯推薦:Scala編程語言專題
表格 5.1 一些基本類型
除了String歸于java.lang包之外,其余所有的基本類型都是包scala的成員。 如,Int的全名是scala.Int。然而,由于包scala和java.lang的所有成員都被每個Scala源文件自動引用,你可以在任何地方只用簡化名(就是說,像Boolean,或Char,或String這樣的名字)。
注意
目前實際上你可以使用與Java的原始類型相一致的Scala值類型的小寫化名。比如,Scala程序里你可以用int替代Int。但請記住它們都是一回事:scala.Int。Scala社區實踐提出的推薦風格是一直使用大寫形式,這也是我們在這本書里做的。為了紀念這個社區推動的選擇,將來Scala的版本可能不再支持乃至移除小寫變體,因此跟隨社區的大流,在你的Scala代碼中使用Int而非int才是明智之舉。
敏銳的Java開發者會注意到Scala的基本類型與Java的對應類型范圍完全一樣。這讓Scala編譯器能直接把Scala的值類型:value type實例,如Int或Double,在它產生的字節碼里轉譯成Java原始類型。
文本
所有在表5.1里列出的基本類型都可以寫成文本:literal。文本是直接在代碼里寫常量值的一種方式。
整數文本
類型Int,Long,Short和Byte的整數文本有三種格式:十進制,十六進制和八進制。整數文本的開頭方式說明了數字的基。如果數開始于0x或0X,那它是十六進制(基于16),并且可能包含從0到9,及大寫或小寫的從A到F的數字。舉例如下:
請注意,不論你用什么形式的整數文本初始化,Scala的shell始終打印輸出基于10的整數值。因此解釋器會把你用文本0x00FF初始化的hex2變量的值顯示為十進制的255。(當然,你也可以不采信我們的話。開始感受語言的好方法是你一邊讀本章的時候一邊在解釋器里試試這些語句。)如果數開始于零,就是八進制(基于8)的,并且只可以包含數字0到7。下面是一些例子:
- scala> val hex = 0x5
- hex: Int = 5
- scala> val hex2 = 0x00FF
- hex2: Int = 255
- scala> val magic = 0xcafebabe
- magic: Int = -889275714
如果數開始于非零數字,并且沒有被修飾過,就是十進制(基于10)的。例如:
- scala> val oct = 035 // (八進制35是十進制29)
- oct: Int = 29
- scala> val nov = 0777
- nov: Int = 511
- scala> val dec = 0321
- dec: Int = 209
如果整數文本結束于L或者l,就是Long類型,否則就是Int類型。一些Long類型的整數文本有:
- scala> val dec1 = 31
- dec1: Int = 31
- scala> val dec2 = 255
- dec2: Int = 255
- scala> val dec3 = 20
- dec3: Int = 20
如果Int類型的文本被賦值給Short或者Byte類型的變量,文本就會被看作是能讓文本值在那個類型有效范圍內那么長的Short或者Byte類型。如:
- scala> val prog = 0XCAFEBABEL
- prog: Long = 3405691582
- scala> val tower = 35L
- tower: Long = 35
- scala> val of = 31l
- of: Long = 31
浮點數文本
- scala> val little: Short = 367
- little: Short = 367
- scala> val littler: Byte = 38
- littler: Byte = 38
浮點數文本是由十進制數字,可選的小數點和可選的E或e及指數部分組成的。下面是一些浮點數文本的例子:
請注意指數部分表示的是乘上以10為底的冪次數。因此,1.2345e1就是1.2345乘以101,等于12.345。如果浮點數文本以F或f結束,就是Float類型的,否則就是Double類型的。可選的,Double浮點數文本也可以D或d結尾。Float文本舉例如下:
- scala> val big = 1.2345
- big: Double = 1.2345
- scala> val bigger = 1.2345e1
- bigger: Double = 12.345
- scala> val biggerStill = 123E45
- biggerStill: Double = 1.23E47
***一個值可以用以下(或其他)格式表示為Double類型:
- scala> val little = 1.2345F
- little: Float = 1.2345
- scala> val littleBigger = 3e5f
- littleBigger: Float = 300000.0
字符文本
- scala> val anotherDouble = 3e5
- anotherDouble: Double = 300000.0
- scala> val yetAnother = 3e5D
- yetAnother: Double = 300000.0
字符文本可以是在單引號之間的任何Unicode字符,如:
除了在單引號之間顯式地提供字符之外,你還可以提供一個表示字符代碼點的前綴反斜杠的八進制或者十六進制數字。八進制數必須在'\0'和'\377'之間。例如字母A的Unicode字符代碼點是八進制101。因此:
- scala> val a = 'A'
- a: Char = A
字符文本同樣可以以前綴\u的四位十六進制數字的通用Unicode字符方式給出,如:
- scala> val c = '\101'
- c: Char = A
實際上,這種unicode字符可以出現在Scala程序的任何地方。例如你可以這樣寫一個標識符:
- scala> val d = '\u0041'
- d: Char = A
- scala> val f = '\u0044'
- f: Char = D
- scala> val B\u0041\u0044 = 1
- BAD: Int = 1
這個標識符被當作BAD,上面代碼里的兩個unicode字符擴展之后的結果。通常,這樣命名標識符是個壞主意,因為它太難讀。然而,這種語法能夠允許含非ASCII的Unicode字符的Scala源文件用ASCII來代表。
表格 5.2 特殊字符文本轉義序列
最終,還有一些字符文本被表示成特殊的轉義序列,參見表格5.2。例如:
字串文本 字串文本由雙引號(")環繞的字符組成:
- scala> val backslash = '\\'
- backslash: Char = \
引號內的字符語法與字符文本相同,如:
- scala> val hello = "hello"
- hello: java.lang.String = hello
由于這種語法對于包含大量轉義序列或跨越若干行的字串很笨拙。因此Scala為原始字串:raw String引入了一種特殊的語法。以同一行里的三個引號(""")開始和結束一條原始字串。內部的原始字串可以包含無論何種任意字符,包括新行,引號和特殊字符,當然同一行的三個引號除外。舉例來說,下面的程序使用了原始字串打印輸出一條消息:
- scala> val escapes = "\\\"\'"
- escapes: java.lang.String = \"'
運行這段代碼不會產生完全符合所需的東西,而是:
- println("""Welcome to Ultamix 3000.
- Type "HELP" for help.""")
原因是第二行前導的空格被包含在了字串里。為了解決這個常見情況,字串類引入了stripMargin方法。使用的方式是,把管道符號(|)放在每行前面,然后在整個字串上調用stripMargin:
- Welcome to Ultamix 3000.
- Type "HELP" for help.
這樣,輸出結果就令人滿意了:
- println("""|Welcome to Ultamix 3000.
- |Type "HELP" for help.""".stripMargin)
符號文本
- Welcome to Ultamix 3000.
- Type "HELP" for help.
符號文本被寫成'< 標識符>,這里< 標識符>可以是任何字母或數字的標識符。這種文本被映射成預定義類scala.Symbol的實例。特別是,文本'cymbal將被編譯器擴展為工廠方法調用:Symbol("cymbal")。符號文本典型的應用場景是你在動態類型語言中使用一個標識符。比方說,或許想要定義個更新數據庫記錄的方法:
方法帶了一個符號參數指明記錄的字段名和一個字段應該更新進記錄的值。在動態類型語言中,你可以通過傳入一個未聲明的字段標識符給方法調用這個操作,但Scala里這樣會編譯不過:
- scala> def updateRecordByName(r: Symbol, value: Any) {
- // code goes here
- }
- updateRecordByName: (Symbol,Any)Unit
基本同樣簡潔的替代方案是,你可以傳遞一個符號文本:
- scala> updateRecordByName(favoriteAlbum, "OK Computer")
- < console>:6: error: not found: value favoriteAlbum
- updateRecordByName(favoriteAlbum, "OK Computer")
除了發現它的名字之外,沒有太多能對符號做的事情:
- scala> updateRecordByName('favoriteAlbum, "OK Computer")
另一件值得注意的事情是符號是被拘禁:interned的。如果你把同一個符號文本寫兩次,那么兩個表達式將指向同一個Symbol對象。
- scala> val s = 'aSymbol
- s: Symbol = 'aSymbol
- scala> s.name
- res20: String = aSymbol
布爾型文本
布爾類型有兩個文本,true和false:
- scala> val bool = true
- bool: Boolean = true
- scala> val fool = false
- fool: Boolean = false
【相關閱讀】