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