一、运算符概述
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等操作。Scala中的运算符主要分为以下五大类:
| 序号 | 运算符类型 | 说明 |
|---|---|---|
| 1 | 算术运算符 | 用于数值类型的加减乘除等运算 |
| 2 | 赋值运算符 | 用于将运算结果赋值给变量 |
| 3 | 比较运算符(关系运算符) | 用于比较两个值的大小关系 |
| 4 | 逻辑运算符 | 用于连接多个条件表达式 |
| 5 | 位运算符 | 用于对二进制位进行操作 |
二、算术运算符
2.1 基本介绍
算术运算符(Arithmetic Operators)是对数值类型的变量进行运算的,在Scala程序中使用非常频繁。
2.2 算术运算符一览表
| 运算符 | 运算 | 范例 | 结果 |
|---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | b=4; -b | -4 |
+ | 加 | 5+5 | 10 |
- | 减 | 6-4 | 2 |
* | 乘 | 3*4 | 12 |
/ | 除 | 5/5 | 1 |
% | 取模(取余) | 7%5 | 2 |
+ | 字符串相加 | "He"+"llo" | "Hello" |
2.3 代码案例演示
objectOperatorDemo{defmain(args:Array[String]):Unit={// 整数除法:只保留整数部分varr1:Int=10/3println("r1="+r1)// 输出: r1=3// 注意:即使赋值给Double,整数除法结果仍是3.0varr2:Double=10/3println("r2="+r2)// 输出: r2=3.0// 小数除法:需要至少一个操作数为小数varr3:Double=10.0/3println("r3="+r3)// 输出: r3=3.3333333333333335println("r3="+r3.formatted("%.2f"))// 输出: r3=3.33// 取模运算println(10%3)// 输出: 1println(-10%3)// 输出: -1println(10%-3)// 输出: 1println(-10%-3)// 输出: -1}}2.4 重要细节说明
⚠️ 细节1:整数除法的陷阱
对于除号/,整数除和小数除是有区别的:
- 整数之间做除法时,只保留整数部分而舍弃小数部分
- 例如:
var x: Int = 10/3,结果是3
⚠️ 细节2:取模运算的本质
当对一个数取模时,可以等价于:
a % b = a - a/b * b这样我们可以看到取模的一个本质运算(和Java的取模规则一样)。
⚠️ 细节3:Scala中没有++、--操作符
注意:Scala中没有
++、--操作符,需要通过+=、-=来实现同样的效果!
varnum=10// num++ // 编译错误!Scala不支持num+=1// 正确:num = 11num-=1// 正确:num = 102.5 课堂练习
练习1:假如还有97天放假,问:xx个星期零xx天?
valdays=97valweeks=days/7// 13周valleftDays=days%7// 余6天println(s"$weeks个星期零$leftDays天")// 输出: 13 个星期零 6 天练习2:华氏温度转摄氏温度,公式为:5/9*(华氏温度-100),测试数据:232.5
valfahrenheit=232.5// 注意:5/9在整数运算中结果为0,需要使用5.0/9valcelsius=5.0/9*(fahrenheit-100)println(s"摄氏温度:$celsius")// 输出: 73.61111111111111三、关系运算符(比较运算符)
3.1 基本介绍
- 关系运算符的结果都是Boolean型,也就是要么是
true,要么是false - 关系表达式经常用在if结构的条件中或循环结构的条件中
- 关系运算符的使用和Java一样
3.2 关系运算符一览表
| 运算符 | 运算 | 范例 | 结果 |
|---|---|---|---|
== | 相等于 | 4==3 | false |
!= | 不等于 | 4!=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
3.3 代码案例演示
objectOperator02{defmain(args:Array[String]):Unit={vara=9varb=8println(a>b)// trueprintln(a>=b)// trueprintln(a<=b)// falseprintln(a<b)// falseprintln(a==b)// falseprintln(a!=b)// true// 可以将关系表达式的结果赋值给Boolean变量varflag:Boolean=a>b println(flag)// true}}3.4 细节说明
- 关系运算符的结果都是Boolean型,也就是要么是
true,要么是false - 关系运算符组成的表达式,我们称为关系表达式。如:
a > b - 比较运算符
"=="不能误写成"="(=是赋值运算符) - 使用陷阱:如果两个浮点数进行比较,应当保证数据类型一致
四、逻辑运算符
4.1 基本介绍
用于连接多个条件(一般来讲就是关系表达式),最终的结果也是一个Boolean值。
4.2 逻辑运算符一览表
假设变量A为true,B为false:
| 运算符 | 描述 | 实例 |
|---|---|---|
&& | 逻辑与 | (A && B)运算结果为false |
|| | 逻辑或 | (A || B)运算结果为true |
! | 逻辑非 | !(A && B)运算结果为true |
4.3 代码案例演示
objectLogicOperatorDemo{defmain(args:Array[String]):Unit={vara=truevarb=falseprintln("a && b = "+(a&&b))// falseprintln("a || b = "+(a||b))// trueprintln("!(a && b) = "+!(a&&b))// true// 短路运算示例varn=5// 因为a为true,所以不会执行后面的n++println(a||(n++>0))// trueprintln("n = "+n)// n = 5(n++未执行)}}五、赋值运算符
5.1 基本介绍
赋值运算符就是将某个运算后的值,赋给指定的变量。
5.2 赋值运算符分类
简单赋值运算符
| 运算符 | 描述 | 实例 |
|---|---|---|
= | 简单的赋值运算符 | C = A + B将A + B表达式结果赋值给C |
复合赋值运算符
| 运算符 | 描述 | 实例 |
|---|---|---|
+= | 相加后再赋值 | C += A等于C = C + A |
-= | 相减后再赋值 | C -= A等于C = C - A |
*= | 相乘后再赋值 | C *= A等于C = C * A |
/= | 相除后再赋值 | C /= A等于C = C / A |
%= | 求余后再赋值 | C %= A等于C = C % A |
<<= | 左移后赋值 | C <<= 2等于C = C << 2 |
>>= | 右移后赋值 | C >>= 2等于C = C >> 2 |
&= | 按位与后赋值 | C &= 2等于C = C & 2 |
^= | 按位异或后赋值 | C ^= 2等于C = C ^ 2 |
|= | 按位或后赋值 | C |= 2等于C = C | 2 |
说明:这部分的赋值运算涉及到二进制相关知识,其运行的规则和Java一样。
5.3 代码案例:交换两个数的值
objectSwapDemo{defmain(args:Array[String]):Unit={vara=10varb=99println("交换前: a="+a+"\tb="+b)// 使用中间变量交换valt=a a=b b=t println("交换后: a="+a+"\tb="+b)}}5.4 赋值运算符特点
- 运算顺序从右往左
- 赋值运算符的左边只能是变量,右边可以是变量、表达式、常量值/字面量
- 复合赋值运算符等价于下面的效果,比如:
a += 3等价于a = a + 3
5.5 面试题:不用中间变量交换两个数
objectInterviewSwap{defmain(args:Array[String]):Unit={vara=10varb=20// 方法1:使用加减法(可能溢出)a=a+b// a = 30b=a-b// b = 10a=a-b// a = 20// 方法2:使用异或运算(推荐)// a = a ^ b// b = a ^ b // b = (a^b)^b = a// a = a ^ b // a = (a^b)^a = bprintln("a="+a+", b="+b)}}六、位运算符
6.1 位运算符一览表
| 运算符 | 描述 | 实例 |
|---|---|---|
& | 按位与运算符 | (a & b)输出结果 12,二进制解释:0000 1100 |
| | 按位或运算符 | (a | b)输出结果 61,二进制解释:0011 1101 |
^ | 按位异或运算符 | (a ^ b)输出结果 49,二进制解释:0011 0001 |
~ | 按位取反运算符 | (~a)输出结果 -61,二进制解释:1100 0011,在一个有符号二进制数的补码形式 |
<< | 左移动运算符 | a << 2输出结果 240,二进制解释:1111 0000 |
>> | 右移动运算符 | a >> 2输出结果 15,二进制解释:0000 1111 |
>>> | 无符号右移 | a >>> 2输出结果 15,二进制解释:0000 1111 |
说明:位运算符的规则和Java一样。
6.2 代码示例
objectBitwiseDemo{defmain(args:Array[String]):Unit={vala=60// 0011 1100valb=13// 0000 1101println("a & b = "+(a&b))// 12 (0000 1100)println("a | b = "+(a|b))// 61 (0011 1101)println("a ^ b = "+(a^b))// 49 (0011 0001)println("~a = "+(~a))// -61 (1100 0011)println("a << 2 = "+(a<<2))// 240 (1111 0000)println("a >> 2 = "+(a>>2))// 15 (0000 1111)}}七、运算符的特别说明
7.1 Scala不支持三目运算符
Scala不支持三目运算符? :,在Scala中使用if-else的方式实现:
// Java中的三目运算符// val num = 5 > 4 ? 5 : 4 // Scala中没有这种写法!// Scala中使用if-else实现valnum=if(5>4)5else4println(num)// 输出: 5💡Scala的设计理念:一种事情尽量只有一种方法完成,这样可以让代码风格更加统一。
7.2 课堂练习
案例1:求两个数的最大值
vala=10valb=20valmax=if(a>b)aelseb println("最大值: "+max)// 20案例2:求三个数的最大值
vala=10valb=20valc=15valmax=if(a>b){if(a>c)aelsec}else{if(b>c)belsec}println("最大值: "+max)// 20八、运算符优先级
8.1 优先级规则
- 运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如下表,上一行运算符总优先于下一行。
- 只有单目运算符、赋值运算符是从右向左运算的。
- 运算符的优先级和Java一样。
8.2 运算符优先级表(从高到低)
| 优先级 | 类别 | 运算符 | 关联性 |
|---|---|---|---|
| 1 | 括号 | ()[] | 左到右 |
| 2 | 单目运算 | !~ | 右到左 |
| 3 | 算术运算符 | */% | 左到右 |
| 4 | 算术运算符 | +- | 左到右 |
| 5 | 移位运算 | >>>>><< | 左到右 |
| 6 | 比较运算符 | >>=<<= | 左到右 |
| 7 | 比较运算符 | ==!= | 左到右 |
| 8 | 位运算 | & | 左到右 |
| 9 | 位运算 | ^ | 左到右 |
| 10 | 位运算 | | | 左到右 |
| 11 | 逻辑运算 | && | 左到右 |
| 12 | 逻辑运算 | || | 左到右 |
| 13 | 赋值运算 | =+=-=*=/=%=>>=<<=&=^=|= | 右到左 |
| 14 | 逗号 | , | 左到右 |
8.3 优先级记忆口诀
1. () [] 2. 单目运算 3. 算术运算符 4. 移位运算 5. 比较运算符(关系运算符) 6. 位运算 7. 关系运算符 8. 赋值运算九、键盘输入语句
9.1 基本介绍
在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。
9.2 Scala实现步骤
- 导入该类所在的包:
import scala.io.StdIn - 直接调用StdIn对象的方法
9.3 代码案例
importscala.io.StdInobjectInputDemo{defmain(args:Array[String]):Unit={println("请输入姓名:")valname=StdIn.readLine()println("请输入年龄:")valage=StdIn.readInt()println("请输入薪水:")valsal=StdIn.readDouble()println(s"姓名:$name, 年龄:$age, 薪水:$sal")}}9.4 与Java的对比
| 功能 | Java实现 | Scala实现 |
|---|---|---|
| 导入 | import java.util.Scanner; | import scala.io.StdIn |
| 创建对象 | Scanner scanner = new Scanner(System.in); | 无需创建对象 |
| 读取字符串 | scanner.next(); | StdIn.readLine() |
| 读取整数 | scanner.nextInt(); | StdIn.readInt() |
| 读取小数 | scanner.nextDouble(); | StdIn.readDouble() |
🎉Scala更简洁!不需要创建Scanner对象,直接调用StdIn的静态方法即可。
十、本章总结
10.1 重点回顾
| 知识点 | 关键内容 |
|---|---|
| 算术运算符 | Scala没有++、--,使用+=、-=替代 |
| 关系运算符 | 结果都是Boolean型,==不要写成= |
| 逻辑运算符 | &&(与)、||(或)、!(非),支持短路运算 |
| 赋值运算符 | 复合赋值运算符如+=、*=等,运算顺序从右往左 |
| 位运算符 | 规则和Java完全一致 |
| 三目运算符 | Scala不支持,使用if-else替代 |
| 运算符优先级 | 和Java一样,可用括号改变优先级 |
| 键盘输入 | 使用scala.io.StdIn,比Java更简洁 |
10.2 Scala vs Java 运算符对比
| 特性 | Scala | Java |
|---|---|---|
++/-- | ❌ 不支持 | ✅ 支持 |
三目运算符? : | ❌ 不支持 | ✅ 支持 |
if-else返回值 | ✅ 有返回值(可替代三目) | ❌ 无返回值 |
| 键盘输入 | StdIn.readXxx() | Scanner.nextXxx() |
| 运算符优先级 | 与Java一致 | 标准优先级 |
十一、课后练习
练习1:判断闰年
编写程序,判断某一年是否为闰年(能被4整除但不能被100整除,或者能被400整除)。
valyear=2024valisLeap=(year%4==0&&year%100!=0)||(year%400==0)println(s"$year是闰年吗?$isLeap")练习2:不使用临时变量交换两个数
vara=10varb=20a=a+b b=a-b a=a-b println(s"a=$a, b=$b")练习3:计算BMI指数
importscala.io.StdIn println("请输入身高(m):")valheight=StdIn.readDouble()println("请输入体重(kg):")valweight=StdIn.readDouble()valbmi=weight/(height*height)valresult=if(bmi<18.5)"偏瘦"elseif(bmi<24)"正常"elseif(bmi<28)"偏胖"else"肥胖"println(s"BMI:${bmi.formatted("%.2f")}, 结果:$result")如果本文对你有帮助,欢迎点赞 👍、收藏 ⭐、评论 💬,你的支持是我持续更新的动力!