Scala编程--基本类型和操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala编程--基本类型和操作相关的知识,希望对你有一定的参考价值。

如果你熟悉Java,你会很开心地发现Java基本类型和操作符在Scala里有同样的意思。然而即使你是一位资深Java开发者,这里也仍然有一些有趣的差别使得本章值得一读。因为本章提到的一些Scala的方面实质上与Java相同,我们插入了一些注释,Java开发者可以安全跳过,以加快你的进程。本章里,你会获得Scala基本类型的概观,包括String和值类型Int,Long,Short,Byte,Float,Double,Char还有Boolean。你会学到可以在这些类型上执行的操作,包括Scala表达式里的操作符优先级是如何工作的。你还会学到隐式转换是如何“丰富”这些基本类型的变体,并带给你那些由Java提供支持之外的附加操作。

5.1 一些基本类型

表格5.1显示了Scala的许多基本的类型和其实例值域范围。总体来说,类型Byte,Short,Int,Long和Char被称为整数类型:integral type。整数类型加上Float和Double被称为数类型:numeric type。

技术分享

除了String归于java.lang包之外,其余所有的基本类型都是包scala的成员。1
目前实际上你可以使用与Java的原始类型相一致的Scala值类型的小写化名。比如,Scala程序里你可以用int替代Int。但请记住它们都是一回事:scala.Int。Scala社区实践提出的推荐风格是一直使用大写形式。

敏锐的Java开发者会注意到Scala的基本类型与Java的对应类型范围完全一样。这让Scala编译器能直接把Scala的值类型:value type实例,如Int或Double,在它产生的字节码里转译成Java原始类型。

5.2 文本

所有在表5.1里列出的基本类型都可以写成文本:literal。文本是直接在代码里写常量值的一种方式。

整数文本

类型Int,Long,Short和Byte的整数文本有三种格式:十进制,十六进制和八进制。整数文本的开头方式说明了数字的基。如果数开始于0x或0X,那它是十六进制(基于16),并且可能包含从0到9,及大写或小写的从A到F的数字。举例如下:

scala> val hex = 0x5 
hex: Int = 5 
scala> val hex2 = 0x00FF 
hex2: Int = 255 
scala> val magic = 0xcafebabe 
magic: Int = -889275714

请注意,不论你用什么形式的整数文本初始化,Scala的shell始终打印输出基于10的整数值。因此解释器会把你用文本0x00FF初始化的hex2变量的值显示为十进制的255。如果数开始于零,就是八进制(基于8)的,并且只可以包含数字0到7。下面是一些例子:

技术分享
scala> val oct = 035 // (八进制35是十进制29) 
oct: Int = 29 
scala> val nov = 0777 
nov: Int = 511 
scala> val dec = 0321 
dec: Int = 209
View Code

如果数开始于非零数字,并且没有被修饰过,就是十进制(基于10)的。例如:

技术分享
1 scala> val dec1 = 31 
2 dec1: Int = 31 
3 scala> val dec2 = 255 
4 dec2: Int = 255
5 scala> val dec3 = 20 
6 dec3: Int = 20
View Code

如果整数文本结束于L或者l,就是Long类型,否则就是Int类型。一些Long类型的整数文本有:

技术分享
scala> val prog = 0XCAFEBABEL 
prog: Long = 3405691582 
scala> val tower = 35L 
tower: Long = 35 
scala> val of = 31l 
of: Long = 31
View Code

如果Int类型的文本被赋值给Short或者Byte类型的变量,文本就会被看作是能让文本值在那个类型有效范围内那么长的Short或者Byte类型。如:

技术分享
1 scala> val little: Short = 367
2 little: Short = 367 
3 scala> val littler: Byte = 38 
4 littler: Byte = 38
View Code

浮点数文本

浮点数文本是由十进制数字,可选的小数点和可选的E或e及指数部分组成的。下面是一些浮点数文本的例子:

技术分享
1 scala> val big = 1.2345 
2 big: Double = 1.2345 
3 scala> val bigger = 1.2345e1 
4 bigger: Double = 12.345 
5 scala> val biggerStill = 123E45 
6 biggerStill: Double = 1.23E47
View Code

请注意指数部分表示的是乘上以10为底的幂次数。因此,1.2345e1就是1.2345乘以101,等于12.345。如果浮点数文本以F或f结束,就是Float类型的,否则就是Double类型的。可选的,Double浮点数文本也可以D或d结尾。Float文本举例如下:

技术分享
1 scala> val little = 1.2345F 
2 little: Float = 1.2345 
3 scala> val littleBigger = 3e5f 
4 littleBigger: Float = 300000.0
View Code

最后一个值可以用以下(或其他)格式表示为Double类型:

技术分享
1 scala> val anotherDouble = 3e5 
2 anotherDouble: Double = 300000.0 
3 scala> val yetAnother = 3e5D 
4 yetAnother: Double = 300000.0
View Code

字符文本

字符文本可以是在单引号之间的任何Unicode字符,如:

技术分享
1 scala> val a = A 
2 a: Char = A
View Code

除了在单引号之间显式地提供字符之外,你还可以提供一个表示字符代码点的前缀反斜杠的八进制或者十六进制数字。八进制数必须在‘\0‘和‘\377‘之间。例如字母A的Unicode字符代码点是八进制101。因此:

scala> val c = \101 
c: Char = A

字符文本同样可以以前缀\u的四位十六进制数字的通用Unicode字符方式给出,如:

技术分享
1 scala> val d = \u0041 
2 d: Char = A 
3 scala> val f = \u0044 
4 f: Char = D
View Code

实际上,这种unicode字符可以出现在Scala程序的任何地方。例如你可以这样写一个标识符:

scala> val B\u0041\u0044 = 1 
BAD: Int = 1

这个标识符被当作BAD,上面代码里的两个unicode字符扩展之后的结果。通常,这样命名标识符是个坏主意,因为它太难读。然而,这种语法能够允许含非ASCII的Unicode字符的Scala源文件用ASCII来代表。

            技术分享

 

最终,还有一些字符文本被表示成特殊的转义序列,参见表格5.2。例如:

技术分享
1 scala> val backslash = \\ 
2 backslash: Char = \
View Code

字串文本

字串文本由双引号(")环绕的字符组成:

技术分享
1 scala> val hello = "hello" 
2 hello: java.lang.String = hello
View Code

引号内的字符语法与字符文本相同,如:

技术分享
1 scala> val escapes = "\\\"\‘" 
2 escapes: java.lang.String = \"
View Code

由于这种语法对于包含大量转义序列或跨越若干行的字串很笨拙。因此Scala为原始字串:raw String引入了一种特殊的语法。以同一行里的三个引号(""")开始和结束一条原始字串。内部的原始字串可以包含无论何种任意字符,包括新行,引号和特殊字符,当然同一行的三个引号除外。举例来说,下面的程序使用了原始字串打印输出一条消息:

技术分享
1 println("""Welcome to Ultamix 3000. Type "HELP" for help.""")
View Code

运行这段代码不会产生完全符合所需的东西,而是:

技术分享
1 Welcome to Ultamix 3000. Type "HELP" for help.
View Code

原因是第二行前导的空格被包含在了字串里。为了解决这个常见情况,字串类引入了stripMargin方法。使用的方式是,把管道符号(|)放在每行前面,然后在整个字串上调用stripMargin:

技术分享
1 println("""|Welcome to Ultamix 3000. 
2                 |Type "HELP" for help.""".stripMargin)        
View Code

这样,输出结果就令人满意了:

技术分享
1 Welcome to Ultamix 3000. 
2 Type "HELP" for help.
View Code

符号文本

符号文本被写成‘<标识符>,这里<标识符>可以是任何字母或数字的标识符。这种文本被映射成预定义类scala.Symbol的实例。特别是,文本‘cymbal将被编译器扩展为工厂方法调用:Symbol("cymbal")。符号文本典型的应用场景是你在动态类型语言中使用一个标识符。比方说,或许想要定义个更新数据库记录的方法:

技术分享
1 scala> def updateRecordByName(r: Symbol, value: Any) { 
2     // code goes here 
3     } 
4 updateRecordByName: (Symbol,Any)Unit
View Code

方法带了一个符号参数指明记录的字段名和一个字段应该更新进记录的值。在动态类型语言中,你可以通过传入一个未声明的字段标识符给方法调用这个操作,但Scala里这样会编译不过:

scala> updateRecordByName(favoriteAlbum, "OK Computer") <console>:6: error: not found: value favoriteAlbum updateRecordByName(favoriteAlbum, "OK Computer")

基本同样简洁的替代方案是,你可以传递一个符号文本:

技术分享
1 scala> updateRecordByName(favoriteAlbum, "OK Computer")
View Code

除了发现它的名字之外,没有太多能对符号做的事情:

scala> val s = aSymbol 
s: Symbol = aSymbol 
scala> s.name 
res20: String = aSymbol

另一件值得注意的事情是符号是被拘禁:interned的。如果你把同一个符号文本写两次,那么两个表达式将指向同一个Symbol对象。

布尔型文本

布尔类型有两个文本,true和false:

技术分享
1 scala> val bool = true 
2 bool: Boolean = true 
3 scala> val fool = false 
4 fool: Boolean = false
View Code

就这些东西了。现在你简直(literally),可以称为Scala的专家了。
5.3 操作符和方法

Scala为它的基本类型提供了丰富的操作符集。如前几章里描述的,这些操作符实际只是作用在普通方法调用上华丽的语法。例如,1 + 2与(1).+(2)其实是一回事。换句话说,就是Int类包含了叫做+的方法,它带一个Int参数并返回一个Int结果。这个+方法在两个Int相加时被调用:

技术分享
1 scala> val sum = 1 + 2 // Scala调用了(1).+(2) 
2 sum: Int = 3
View Code

想要证实这点,可以把表达式显式地写成方法调用:

技术分享
1 scala> val sumMore = (1).+(2) 
2 sumMore: Int = 3
View Code

而真正的事实是,Int包含了许多带不同的参数类型的重载:overload的+方法例如,Int还有另一个也叫+的方法参数和返回类型为Long。如果你把Long加到Int上,这个替换的+方法就将被调用:

scala> val longSum = 1 + 2L // Scala调用了(1).+(2L) 
longSum: Long = 3

符号+是操作符——更明确地说,是中缀操作符。操作符标注不仅限于像+这种其他语言里看上去像操作符一样的东西。你可以把任何方法都当作操作符来标注。例如,类String有一个方法indexOf带一个Char参数。indexOf方法搜索String里第一次出现的指定字符,并返回它的索引或-1如果没有找到。你可以把indexOf当作中缀操作符使用,就像这样:

技术分享
1 scala> val s = "Hello, world!" 
2 s: java.lang.String = Hello, world! 
3 scala> s indexOf o // Scala调用了s.indexOf(’o’) 
4 res0: Int = 4
View Code

另外,String提供一个重载的indexOf方法,带两个参数,分别是要搜索的字符和从哪个索引开始搜索。(前一个indexOf方法开始于索引零,也就是String开始的地方。)尽管这个indexOf方法带两个参数,你仍然可以用操作符标注的方式使用它。不过当你用操作符标注方式调用带多个参数的方法时,这些参数必须放在括号内。例如,以下是如何把另一种形式的indexOf当作操作符使用的例子(接前例):

技术分享
1 scala> s indexOf (o, 5) // Scala调用了s.indexOf(’o’, 5) 
2 res1: Int = 8
View Code

技术分享

目前为止,你已经看到了中缀:infix操作符标注的例子,也就是说调用的方法位于对象和传递给方法的参数或若干参数之间,如“7 + 2”。Scala还有另外两种操作符标注:前缀和后缀。前缀标注中,方法名被放在调用的对象之前,如,-7里的‘-’。后缀标注中,方法放在对象之后,如,“7 toLong”里的“toLong”

与中缀操作符——操作符带后两个操作数,一个在左一个在右——相反,前缀和后缀操作符都是一元:unary的:它们仅带一个操作数。前缀方式中,操作数在操作符的右边。前缀操作符的例子有-2.0,!found和~0xFF。与中缀操作符一致,这些前缀操作符是在值类型对象上调用方法的简写方式。然而这种情况下,方法名在操作符字符上前缀了“unary_”。例如,Scala会把表达式-2.0转换成方法调用“(2.0).unary_-”。你可以输入通过操作符和显式方法名两种方式对方法的调用来演示这一点:

技术分享
1 scala> -2.0 // Scala调用了(2.0).unary_- 
2 res2: Double = -2.0 
3 scala> (2.0).unary_- 
4 res3: Double = -2.0
View Code

 

以上是关于Scala编程--基本类型和操作的主要内容,如果未能解决你的问题,请参考以下文章

scala 基本类型和操作

Scala编程--基本类型和操作

Scala 基础—— 基础类型和基础操作

Scala基本语法及操作程序控制结构

scala基本数据类型

2021年大数据常用语言Scala:基础语法学习 数据类型与操作符