![Scala编程(第4版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/353/38381353/b_38381353.jpg)
5.2 字面量
表5.1中列出的所有基础类型都可以用字面量(literal)来书写。字面量是在代码中直接写入常量值的一种方式。
Java程序员的快速通道
本节中展示的大部分字面量的用法跟Java完全一致,如果你是Java大师,可以安全地跳过本节的绝大部分内容。你需要读一读的是Scala原生字符串和符号的字面量(74页开始)以及字符串插值(77页开始)。还有就是Scala并不支持八进制字面量和以0开头的整数字面量,比如031,将无法编译通过。
整数字面量
用于Int、Long、Short和Byte的整数字面量有两种形式:十进制的和十六进制的。整数字面量的不同开头表示了不同的进制。如果以0x或0X开头,意味着这是十六进制的数,可以包含0到9以及大写或小写的A到F表示的数字。例如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-104-1.jpg?sign=1739151440-Wg7RhbyC5uuKzCJZWA0wcrP0WV0uS89G-0-3b19b5e29096503bd461ff9e42a63313)
注意,Scala的shell总是以十进制打印整数值,不论用哪种形式来初始化。因此解释器把用字面量0x00FF初始化的变量hex2显示为十进制的255(当然,不必盲目相信我们说的,感受Scala的好方法是一边读一边在解释器中尝试这些语句)。如果字面量以非0的数字打头,且除此之外没有其他修饰,那么它就是十进制的。例如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-104-2.jpg?sign=1739151440-VFZK8rcPB1GHPRKdjKD4k9c2xUdv0zr7-0-6e1dda0c92d06fb04caefbb595b72ef9)
如果整数字面量以L或l结尾,那么它就是Long类型的,否则就是Int类型的。一些Long类型的整数字面量如下:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-105-1.jpg?sign=1739151440-a5FfBCmN61OQiowUJQmP90ZCRJb8Ifft-0-f454287c7baac34dc596a9d32846ee0d)
如果一个Int类型的字面量被赋值给一个类型为Short或Byte的变量,该字面量会被当作Short或Byte类型,只要这个字面量的值在对应类型的合法取值区间即可。例如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-105-2.jpg?sign=1739151440-TYgNw86cZapI2NaKD4pnC5RKQQlWgYT3-0-dfee17ec89f80de1a286738cbe9b4c05)
浮点数字面量
浮点数字面量由十进制的数字、可选的小数点(decimal point),以及后续一个可选的E或e打头的指数(exponent)组成。一些浮点数字面量如下:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-105-3.jpg?sign=1739151440-rw1wMmzFgSAbNg38Okdfmv4fjsZGzMjr-0-a7316b882c201a8895a52e310579f328)
注意,指数部分指的是对前一部分乘以10的多少次方。因此,1.2345e1等于1.2345乘以101,即12.345。如果浮点数字面量以F或f结尾,那它就是Float类型的;否则它就是Double类型的。Double类型的浮点数字面量也可以以D或d结尾,但这是可选的。一些Float字面量如下:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-106-1.jpg?sign=1739151440-TeGbVbKVS0EpYGupeqpWpJarYIk2RkLi-0-8c95d7486c5475d1fee8bb769b90554b)
如果要以Double来表示最后这个浮点数值,可以用下面(或其他)的形式:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-106-2.jpg?sign=1739151440-rChYVHJXJ4OiO9tI8vYb6TX0CKFyURha-0-1e49540292fe2453bd4cc425182848a7)
字符字面量
字符字面量(character literal)由一对单引号和中间的任意Unicode字符组成,例如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-106-3.jpg?sign=1739151440-eZJd6spa5M18Zo3BIboVypAbEDMtbObT-0-8d4c9426bf5c753f62c4b1d3588192d1)
除了显式地给出原字符,也可以用字符的Unicode码来表示。具体写法是\u加上Unicode码对应的四位的十六进制数字,如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-106-4.jpg?sign=1739151440-Q0e4Ph7al8xXsdNku8ZHk4jGuy00LvH2-0-c45d192ab9fc32416a3a374b82c60d5b)
事实上,这样的Unicode字符可以出现在Scala程序的任何位置。比如说,可以像这样命名一个标识符(变量):
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-106-5.jpg?sign=1739151440-8jSfDZwNFCjENr9zow3PGBwN7WXMRe7O-0-e4734d9c4a9d944d9bf45c8ebd064be2)
这个标识符跟BAD一样处理,也就是将上述Unicode码解开后的结果。通常来说,把标识符命名成这样并不好,因为不易读。这样的语法规则的存在,本意是让包含非ASCII的Unicode字符的Scala源文件可以用ASCII表示。
最后,还有一些字符字面量是由特殊的转义序列来表示的,如表5.2所示。例如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-107-1.jpg?sign=1739151440-NVBPXkcvtPJAipn9Th4hlPpnuyawEQxc-0-0c767df64c4c1a1620dcfe3aa74e3e90)
表5.2 特殊字符转义序列
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-107-2.jpg?sign=1739151440-uchF1e1e8tsSofizn3uDKaNDxmGVFc8n-0-a8782c3488beba550c45b954e1bb4397)
字符串字面量
字符串字面量由双引号包起来的字符组成:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-107-3.jpg?sign=1739151440-fTQcCJlv2HFfYPN105Rd4LLgkFASChw3-0-988317fa0d8af4c81ddf7b70fd57f641)
双引号中字符的语法跟字符字面量一样。比如:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-107-4.jpg?sign=1739151440-ko4y9F4wXm6R9MDVZRf7fegpTajn5VU9-0-059a57a55c5cb63cbbacb5d9779c08f7)
由于这个语法对那些包含大量转义序列或者跨多行的字符串而言比较别扭,Scala支持一种特殊的语法来表示原生字符串(raw string)。可以用三个双引号(""")开始并以三个双引号(""")结束来表示原生字符串。原生字符串内部可以包含任何字符,包括换行、单双引号和其他特殊字符。当然,连续三个双引号的情况除外。例如,如下程序就是用原生字符串来打印一条消息:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-108-1.jpg?sign=1739151440-mArmxm1LYLFyXYSFXxEccYlogyegVfNN-0-15675a1ce5e151c12a36ed023b4ab591)
不过,运行这段代码并不会产生跟我们想要的完全一致的输出:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-108-2.jpg?sign=1739151440-fIlGmQH0qeKcG6jssIflGwWTP6TB7dfY-0-118263c886a4eb5e36701ae019cf1024)
这里的问题是字符串第二行前面的空格被包含在了字符串里!为了处理这个常见的情况,可以对字符串调用stripMargin方法。具体做法是在每一行开始加一个管道符(|),然后对整个字符串调用stripMargin:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-108-3.jpg?sign=1739151440-motOJDHlOu0iPsBiEDGnWLuHUqrOMqCU-0-866ab1786c0247b7ba8264d2affacdf8)
现在这段代码满足我们的要求了:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-108-4.jpg?sign=1739151440-bEzlf1Tox75fRjH6Enxjtruw9Ws8SLXu-0-c062c76169ac3db3b2576dd696703ece)
符号字面量
符号字面量(symbol literal)的写法是'ident,其中ident可以是任何由字母和数字组成的标识符。这样的字面量会被映射成scala.Symbol这个预定义类的实例。确切地说,字面量'cymbal会被编译器展开成一个工厂方法的调用:Symbol("cymbal")。符号字面量通常用在那些在动态类型语言中用来当作标识符的场合。比如,你可能想要定义一个更新数据库记录的方法:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-108-5.jpg?sign=1739151440-3j93jmA2LQM9iGRErLMhNdOQmP6co0Vn-0-a92d42e581408b0fc7cffbcdbd4a4b7b)
这个方法以参数的形式接收一个符号和一个值,分别表示记录中要更新的字段和值。在动态类型语言中,可以传入一个未声明的字段标识符来调用这个方法,但在Scala中这样是行不通的:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-109-1.jpg?sign=1739151440-9ux3CskGYuiKz7bde0QJdK1wIFYMB4uw-0-1289232cc31e93d82d6395368db6acb1)
不过,可以传入一个符号字面量,几乎(跟动态语言)同样精简:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-109-2.jpg?sign=1739151440-M7s37UwZqMtEijVReoRMK2MKiYTDIVRi-0-90057c2c1133d7cb2128e506d4d41982)
对于符号,你能做的不多,除了获取它的名称:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-109-3.jpg?sign=1739151440-aVHVNbfBuXWS2grBlnoHEkwcu8ihpTGQ-0-949c9bb9f26a48c0ab056de4f5d87eaa)
另一个值得注意的点是符号会被内部化。[2]如果同样的符号字面量出现两次,这两次引用都会指向同一个Symbol对象。
布尔值字面量
类型Boolean有两个字面量,true和false:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-109-4.jpg?sign=1739151440-UNexDjPHW88Cob0KvBsoypN5QstbPuUP-0-e76aa086697755d968bc46110457da89)
关于字面量的内容就这些。从“字面”上讲,你已经是Scala的专家了。