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

如果数开始于非零数字,并且没有被修饰过,就是十进制(基于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

如果整数文本结束于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

如果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

浮点数文本

浮点数文本是由十进制数字,可选的小数点和可选的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

请注意指数部分表示的是乘上以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

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

1 scala> val anotherDouble = 3e5
2 anotherDouble: Double = 300000.0
3 scala> val yetAnother = 3e5D
4 yetAnother: Double = 300000.0

字符文本

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

1 scala> val a = ‘A‘
2 a: Char = A

除了在单引号之间显式地提供字符之外,你还可以提供一个表示字符代码点的前缀反斜杠的八进制或者十六进制数字。八进制数必须在‘\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

实际上,这种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 = \

字串文本

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

1 scala> val hello = "hello"
2 hello: java.lang.String = hello

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

1 scala> val escapes = "\\\"\‘"
2 escapes: java.lang.String = \"‘

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

1 println("""Welcome to Ultamix 3000. Type "HELP" for help.""")

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

1 Welcome to Ultamix 3000. Type "HELP" for help.

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

1 println("""|Welcome to Ultamix 3000.
2                 |Type "HELP" for help.""".stripMargin)        

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

1 Welcome to Ultamix 3000.
2 Type "HELP" for help.

符号文本

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

1 scala> def updateRecordByName(r: Symbol, value: Any) {
2     // code goes here
3     }
4 updateRecordByName: (Symbol,Any)Unit

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

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

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

1 scala> updateRecordByName(‘favoriteAlbum, "OK Computer")

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

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

就这些东西了。现在你简直(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

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

1 scala> val sumMore = (1).+(2)
2 sumMore: Int = 3

而真正的事实是,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

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

1 scala> s indexOf (‘o‘, 5) // Scala调用了s.indexOf(’o’, 5)
2 res1: Int = 8

目前为止,你已经看到了中缀: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

时间: 2024-10-20 15:28:07

Scala编程--基本类型和操作的相关文章

scala 基本类型和操作

基本类型和操作========================类型说明,与java一致值类型 范围 Byte 8位有符号补码整数(-27-27-1) Short 16位有符号补码整数(-215-215-1) Int 32位有符号补码整数(-231-231-1) Long 64位有符号补码整数(-263-263-1) Char 16位无符号Unicode字符(0-216-1) String 字符序列 Float 32位IEEE754单精度浮点数 Double 64位IEEE754单精度浮点数 Bo

scala编程(五)——基本类型和操作

文本 文本是直接在代码里写常量值的一种方式以.在Scala中并不显式的使用Int或float,而是以文本的方式写成 val 变量. 如果整数文本结束于 L 或者 l,就是 Long 类型,否则就是 Int 类型. 如果浮点数文本以F或f结束,就是Float类型的,否则就是Double类型的. 可选的,Double浮点数文本也可以D或d结尾. 字符文本可以是在单引号之间的任何 Unicode 字符 def main(args: Array[String]): Unit = { val l = 1l

Scala编程入门---数组操作之数组转换

使用yield和函数式编程转换数组 //对Array进行转换,获取的还是Aarry val a = Array(1,2,3,4,5) val a2 = for(ele <- a) yield ele * ele //对ArrayBuffer进行转换,获取的还是ArrayBuffer val b = ArrayBuffer[Int]() b+=(1,2,3,4,5) val b2=for(ele <- b) yield ele*ele //结合if守卫, 仅转换需要元素 val a3= for(

Dataflow编程模型和spark streaming结合

Dataflow编程模型和spark streaming结合 主要介绍一下Dataflow编程模型的基本思想,后面再简单比较一下Spark  streaming的编程模型 == 是什么 == 为用户提供以流式或批量模式处理海量数据的能力,该服务的编程接口模型(或者说计算框架)也就是下面要讨论的dataflow model 流式计算框架处理框架很多,也有大量的模型/框架号称能较好的处理流式和批量计算场景,比如Lambda模型,比如Spark等等,那么dataflow模型有什么特别的呢? 这就要要从

JavaScript基本类型和引用类型的值

JS变量可能包含两种不同数据类型的值:基本类型值和引用类型值.基本类型指的是简单的数据段,而引用类型值那些由多个值构成的对象: 在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值.JS有5种基本数据类型:Undefined, Null,Boolean,Number和String.这5种基本数据类型是按值访问的.因为可以操作保存在变量中的实际的值. 引用类型的值保存在内存中的对象.与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间.

【Scala编程】函数式风格编写排序算法

有关Scala编程实例 在刚开始学习一门编程语言的时候,总是想去写一些比较大的程序和项目,但是由于基础不扎实,往往欲速则不达.所以,只能一步一步来,通过一些经典的小例子来实践和锻炼,最终不断加深编程的技能,坚持下来,相信慢慢就能够变得熟练. 冒泡排序.选择排序.插入排序的一般写法 这三种排序方法没有太多要说的东西,这里的编程方式和指定式方式没什么差别. 这里之所以使用Array数据,因为Array数组是可变的对象序列,其元素值可以改变,而List类对象的元素是不可变的. 这里的写法不是函数式风格

javascript 数据类型(基本类型和引用类型的定义和区别)

ECMAStript变量包含两种不同类型的值,基本类型和引用类型. 基本类型:指的就是保存在栈内存中的简单数据段. 引用类型:指的是那些保存在堆内存中的对象,换句话说,就是变量名实际上是一个指针,而这个指针指向的位置,就是保存对象的位置. 两种不同的访问方式 基本类型:按值访问,操作的是它们实际的值. 引用类型:按引用访问,当查询时,我们需要先从栈中读取内存地址,然后按照指针所指向的地方,找到堆内存里面的值. 基本类型 基本的数据类型有:`undefined,boolean,number,str

Javascript中的基本类型和引用类型

一.基本类型和引用类型概述 js中数据类型的值包括:基本类型值和引用类型值 基本数据类型:undefined;null;boolean;number;string 引用类型值:保存在内存中,js不允许直接访问内存位置,因此时操作引用而不是实际对象 二.如何检测数据类型 1.基本数据类型的检测:使用typeof var s = "AAA"; alert(typeof s); //返回string `     2.引用类型(对象类型)检测:使用instanceof alert(person

基本类型和引用类型

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC" } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; min-height: 1