文章目录
- 零、本讲学习目标
- 一、运算符等价于方法
- (一)运算符即方法
- (二)方法即运算符
- 1、单参方法
- 2、多参方法
- 3、无参方法
- 二、Scala运算符
- (一)运算符分类表
- (二)Scala与Java运算符比较
- 三、运算符种类
- (一)中缀运算符(Infix Operator)
- (二)前缀运算符(Prefix Operator)
- (三)后缀运算符(Postfix Operator)
- 四、运算符优先级
- (一)简单说明
- (二)运算优先级表
- 五、课后作业
零、本讲学习目标
- 理解Scala运算符与方法的等价性
- 掌握Scala常用运算符
- 理解Scala运算符种类
一、运算符等价于方法
- Scala中运算符即方法、方法即运算符。Scala中运算符其实是普通方法调用的另一种表现形式,运算符的使用其实就是隐含地调用对应的方法。
(一)运算符即方法
op
运算符与.op
方法调用是等价的,op
表示运算符:+
、-
、*
、/
……- 演示
x + y
与x.+(y)
的等价性
(二)方法即运算符
1、单参方法
val str = "abcdef"
val x1 = str.indexOf('c')
val x2 = str indexOf 'c'
str.indexOf('c')
与str indexOf 'c'
是等价的
2、多参方法
val x3 = str.substring(2, 4)
val x4 = str substring (2, 4) // 如果参数有多个,需要用小括号包起来
str.substring(2, 4)
与str substring (2, 4)
是等价的
3、无参方法
val x5 = str.toUpperCase()
val x6 = str.toUpperCase // 方法调用时如果不需要传入任何参数,小括号可以省略
val x7 = str toUpperCase // 这种写法,如果没有参数,则括号不用写
- 注意:使用后缀运算符
toUpperCase
之前必须导入scala.language.postfixOps
类,否则会报错
import scala.language.postfixOps
val x5 = str.toUpperCase()
val x6 = str.toUpperCase // 方法调用时如果不需要传入任何参数,小括号可以省略
val x7 = str toUpperCase // 这种写法,如果没有参数,则括号不用写
二、Scala运算符
(一)运算符分类表
运算符类型 | 运算符 |
---|---|
算术运算 | +、-、*、/ |
关系运算 | >、<、>=、<= |
逻辑运算 | `&& 、 |
位运算 | `>>、>>>、<< 、~、 &、 |
比较运算 | ==、!= |
(二)Scala与Java运算符比较
-
Scala和Java运算符基本相同,不同之处在于比较运算符。
-
Java中,如果是基本数据类型,
==
与!=
比较的是值;如果是复杂数据类型,比较的是对象的地址,如果不是想比较地址而是想比较真正的内容,则需要使用equals
方法。
-
Scala中,如果是基本数据类型,
==
与!=
比较的是值;如果是复杂数据类型,会隐含地调用equals
进行比较,这也就意味着 Scala中不存在Java中经典的equals
问题。
val a = 100
val b = a + 0
a == b
val str1 = "Scala"
val str2 = str1 + ""
str1 == str2
str1.equals(str2)
三、运算符种类
(一)中缀运算符(Infix Operator)
- 运算符符在两个操作数之间,
2 + 3
等同于2.+(3)
(二)前缀运算符(Prefix Operator)
-
运算符在唯一的操作数之前 :
-
1、+
3、~
0xFF、!
false -
-1
等同于1.unary_-
,前缀运算符如同中缀运算符一样,也是方法调用的另一种方式,不同的是,方法名要在符号前加上前缀unary_
。
-
能作为前缀运算符的运算符只有
+、-、!、~
四种。如果你自己定义了unary_!
方法就可以使用!
前缀运算符来调用方法了,但是即使你定义了unary_*
,*
也不能用来调用该方法,因为*
不是四种可用的前缀运算符之一。
(三)后缀运算符(Postfix Operator)
- 运算符在唯一的操作数之后
str toUpperCase
等同于str.toUpperCase()
,后缀运算符不用点或括号调用无参方法。在Scala里,方法调用的空括号可以省略,但是如果去掉括号可能造成副作用就带上括号。
四、运算符优先级
(一)简单说明
-
由于Scala并没有真正的运算符,运算符其实是方法的一种形式,所以此处运算符的优先级,其实就是指方法的优先级。在Scala中方法的执行是有优先级的区别的,这也是为了解决传统运算符优先级问题。
-
例如:
3 + 2 * 5
,我们期望获得的是13
,但是根据Scala特点,Scala中所有运算符其实就是方法,那么按照这种说法,表达式应该等同于(3).+(2)
得到5
,(5).*(5)
得到25
,与我们的预期不符!Scala如何解决此问题呢?靠的是运算符优先级。
(二)运算优先级表
- 具有最高优先级的运算符在表的顶部,那些优先低级排在底部。在一个表达式,优先级高的运算符将首先计算。
分类 | 运算符 | 关联 |
---|---|---|
Postfix | ()、 [] | 从左到右 |
Unary | ! 、~ | 从右到左 |
Multiplicative | *、 /、 % | 从左到右 |
Additive | +、 - | 从左到右 |
Shift | >>、 >>>、 << | 从左到右 |
Relational | >、 >=、 <、 <= | 从左到右 |
Equality | ==、 != | 从左到右 |
Bitwise | AND、& | 从左到右 |
Bitwise | XOR、^ | 从左到右 |
Bitwise | OR、 | | 从左到右 |
Logical | AND、&& | 从左到右 |
Logical OR | || | 从左到右 |
Assignment | =、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|= | 从右到左 |
Comma | , | 从左到右 |
- 如果运算符以
=
结尾,且运算符并非比较运算符<=
、>=
、==
或=
,则运算符优先级等同于=
,即优先级最低,例如+=
、-=
等;同级别优先级从左到右统计;可以使用括号改变优先级,这是个好习惯,特别是在Scala这种可能过于简洁的语言中。 - 特殊情况:以
:
字符结尾的方法由它的右操作数调用,并传入左操作数,以其它字符结尾的方法与之相反。a :: b
对应的是(b).::(a)
而不是(a).::(b)
。
五、课后作业
- 在Scala交互模式下尝试Scala的各种运算符,熟悉Scala运算符的优先级