Scala 运算符
在 Scala 中,运算符(Operators)是用于执行计算、比较或逻辑操作的特殊符号或关键字。Scala 没有独立的运算符语法,所有的运算符实际上是方法调用,这使得 Scala 的运算符非常灵活,支持自定义运算符。本篇将以简洁清晰的方式讲解 Scala 的运算符,涵盖分类、用法、优先级和注意事项,适合初学者理解。
1. 运算符概述
- 定义:运算符是用于操作数据的符号(如
+
,-
,==
),在 Scala 中,运算符是对象方法的中缀表示形式。例如,a + b
等价于a.+(b)
。 - 特点:
- 运算符是方法,允许自定义(如重载
+
方法)。 - 支持中缀、前缀和后缀表示法。
- Scala 没有传统语言的
++
或--
运算符。 - 分类:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 其他特殊运算符
2. 运算符分类及用法
1. 算术运算符
用于数值计算,返回数值结果。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
+ | 加法 | val x = 5 + 3 | x = 8 |
- | 减法 | val x = 5 - 3 | x = 2 |
* | 乘法 | val x = 5 * 3 | x = 15 |
/ | 除法 | val x = 10 / 3 | x = 3 |
% | 取模 | val x = 10 % 3 | x = 1 |
注意:
- 整数除法(
/
)返回整数,舍去小数部分。 - 浮点数运算需要显式使用
Double
或Float
:
val x = 10.0 / 3 // 输出: 3.333...
2. 关系运算符
用于比较两个值,返回 Boolean
结果。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
== | 等于 | 5 == 3 | false |
!= | 不等于 | 5 != 3 | true |
> | 大于 | 5 > 3 | true |
< | 小于 | 5 < 3 | false |
>= | 大于等于 | 5 >= 5 | true |
<= | 小于等于 | 5 <= 3 | false |
注意:
==
比较值相等性,而非引用相等(类似 Java 的equals
)。- 引用相等使用
eq
(AnyRef
类型),如str1 eq str2
。
3. 逻辑运算符
用于布尔值逻辑运算,返回 Boolean
结果。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
&& | 逻辑与 | true && false | false |
|| | 逻辑或 | true || false | true |
! | 逻辑非 | !true | false |
注意:
&&
和||
支持短路求值(如果左侧表达式已确定结果,右侧不执行)。- 示例:
val x = false && { println("Not executed"); true } // 不打印
4. 位运算符
用于整数的位操作。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
& | 按位与 | 5 & 3 | 1 |
| | 按位或 | 5 | 3 | 7 |
^ | 按位异或 | 5 ^ 3 | 6 |
~ | 按位取反 | ~5 | -6 |
<< | 左移 | 5 << 1 | 10 |
>> | 右移 | 5 >> 1 | 2 |
>>> | 无符号右移 | 5 >>> 1 | 2 |
示例:
val a = 5 // 二进制: 0101
val b = 3 // 二进制: 0011
println(a & b) // 输出: 1 (0001)
println(a | b) // 输出: 7 (0111)
5. 赋值运算符
用于更新变量值。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | var x = 5 | x = 5 |
+= | 加并赋值 | x += 3 | x = 8 |
-= | 减并赋值 | x -= 3 | x = 2 |
*= | 乘并赋值 | x *= 2 | x = 10 |
/= | 除并赋值 | x /= 2 | x = 2 |
%= | 取模并赋值 | x %= 3 | x = 2 |
&= | 按位与并赋值 | x &= 3 | 按位操作 |
|= | 按位或并赋值 | x |= 3 | 按位操作 |
^= | 按位异或并赋值 | x ^= 3 | 按位操作 |
<<= | 左移并赋值 | x <<= 1 | 按位操作 |
>>= | 右移并赋值 | x >>= 1 | 按位操作 |
注意:仅 var
变量支持赋值运算符,val
不允许重新赋值。
6. 其他特殊运算符
- 范围运算符:
to
,until
(用于创建范围):
val range1 = 1 to 5 // 包含 5: Range(1, 2, 3, 4, 5)
val range2 = 1 until 5 // 不包含 5: Range(1, 2, 3, 4)
- 字符串插值:虽非传统运算符,但常与运算结合:
val x = 5
println(s"Value: $x") // 输出: Value: 5
- 自定义运算符:任何方法名都可以用作中缀运算符:
class MyNum(n: Int) {
def ++(other: MyNum) = MyNum(n + other.n)
}
val a = MyNum(2)
val b = MyNum(3)
println((a ++ b).n) // 输出: 5
3. 运算符优先级
Scala 的运算符优先级按方法名首字符和符号类型决定,从高到低如下:
优先级 | 运算符示例 |
---|---|
1 | 自定义运算符(字母开头,如 max ) |
2 | * , / , % |
3 | + , - |
4 | > , < , >= , <= |
5 | == , != |
6 | & |
7 | ^ |
8 | | |
9 | && |
10 | || |
11 | = , += , -= , 其他赋值运算符 |
示例:
val x = 2 + 3 * 4 // 3 * 4 先计算,结果: 14
println(x)
- 括号优先:使用
()
显式指定优先级:
val y = (2 + 3) * 4 // 结果: 20
4. 注意事项
- 运算符即方法:
a + b
等价于a.+(b)
,支持自定义运算符。 - 无
++
或--
:Scala 不支持++
或--
,需用+= 1
或-= 1
:
var x = 5
x += 1 // 正确
// x++ // 错误
- 类型安全:运算符操作需类型匹配,否则编译报错:
// val x = 5 + "Scala" // 错误:类型不匹配
- 短路求值:
&&
和||
只在必要时计算右侧表达式。 - Scala 2 vs Scala 3:
- Scala 3 语法更严格,但运算符行为一致。
- Scala 3 增强了类型推断和错误提示。
5. 实践示例
综合示例,展示多种运算符的使用:
object OperatorDemo {
def main(args: Array[String]): Unit = {
// 算术运算符
val a = 10
val b = 3
println(s"Add: ${a + b}, Subtract: ${a - b}, Multiply: ${a * b}, Divide: ${a / b}, Mod: ${a % b}")
// 关系运算符
println(s"Equal: ${a == b}, Greater: ${a > b}")
// 逻辑运算符
val x = true
val y = false
println(s"And: ${x && y}, Or: ${x || y}, Not: ${!x}")
// 位运算符
println(s"Bitwise AND: ${a & b}, OR: ${a | b}, Shift: ${a << 1}")
// 赋值运算符
var c = 5
c += 2
println(s"Assign: $c")
// 范围运算符
val range = 1 to 3
println(s"Range: ${range.mkString(", ")}")
}
}
输出:
Add: 13, Subtract: 7, Multiply: 30, Divide: 3, Mod: 1
Equal: false, Greater: true
And: false, Or: true, Not: false
Bitwise AND: 2, OR: 11, Shift: 20
Assign: 7
Range: 1, 2, 3
6. 学习建议
- 实践:在 Scala REPL(运行
scala
命令)中测试运算符,观察类型推断和优先级。 - 函数式思维:尽量避免使用赋值运算符(如
+=
),优先用不可变变量(val
)。 - 自定义运算符:尝试在类中定义自定义运算符,体验 Scala 的灵活性。
- 资源:
- 官方文档:https://www.scala-lang.org/
- Scala Exercises (https://www.scala-exercises.org/)
- 《Programming in Scala》by Martin Odersky
如果需要深入讲解某一运算符(如位运算或自定义运算符)或更多示例,请告诉我!