Appearance
第2课:运算符
🎯 学习目标
- 掌握算术运算符、关系运算符、逻辑运算符
- 理解位运算符的使用场景
- 掌握运算符优先级和结合性
- 理解短路运算和副作用
📖 一、算术运算符
基本算术运算
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
| + | 加法 | 5 + 3 | 8 |
| - | 减法 | 5 - 3 | 2 |
| * | 乘法 | 5 * 3 | 15 |
| / | 除法 | 5 / 2 | 2(整数除法) |
| % | 取余 | 5 % 2 | 1 |
java
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3(整数除法)
System.out.println(a % b); // 1(余数)一元运算符
java
int x = 5;
System.out.println(+x); // 5(正号)
System.out.println(-x); // -5(负号)
int y = 10;
y++; // y = y + 1,后置自增
++y; // y = y + 1,前置自增
y--; // y = y - 1,后置自减
--y; // y = y - 1,前置自减⚠️ 前置与后置的区别:
java
int a = 5;
int b = a++; // b = 5, a = 6(先赋值,后自增)
int c = ++a; // c = 7, a = 7(先自增,后赋值)
System.out.println("a = " + a); // 7
System.out.println("b = " + b); // 5
System.out.println("c = " + c); // 7📖 二、关系运算符(比较运算符)
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
| == | 等于 | 5 == 3 | false |
| != | 不等于 | 5 != 3 | true |
| > | 大于 | 5 > 3 | true |
| >= | 大于等于 | 5 >= 5 | true |
| < | 小于 | 5 < 3 | false |
| <= | 小于等于 | 5 <= 5 | true |
java
int a = 10, b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a > b); // false
System.out.println(a < b); // true⚠️ 字符串比较陷阱:
java
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true(字符串池)
System.out.println(s1 == s3); // false(不同对象)
System.out.println(s1.equals(s3)); // true(正确比较内容)
// 关键:== 比较引用,equals() 比较内容📖 三、逻辑运算符
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
| && | 逻辑与(短路) | true && false | false |
| || | 逻辑或(短路) | true || false | true |
| ! | 逻辑非 | !true | false |
| & | 逻辑与(不短路) | true & false | false |
| | | 逻辑或(不短路) | true | false | true |
短路运算
java
int a = 5, b = 10;
// && 短路:左侧为 false,右侧不执行
if (a > 10 && b++ > 5) {
System.out.println("条件成立");
}
System.out.println("b = " + b); // b = 10(b++ 没有执行)
// || 短路:左侧为 true,右侧不执行
if (a < 10 || b++ > 5) {
System.out.println("条件成立");
}
System.out.println("b = " + b); // b = 10(b++ 没有执行)
// & 不短路:两侧都执行
if (a > 10 & b++ > 5) {
System.out.println("条件成立");
}
System.out.println("b = " + b); // b = 11(b++ 执行了)💡 最佳实践:
- 通常使用 && 和 ||(短路版本)
- 性能更好,避免不必要的计算
- 避免空指针:
if (obj != null && obj.method())
📖 四、赋值运算符
| 运算符 | 说明 | 示例 | 等价于 |
|---|---|---|---|
| = | 赋值 | a = 5 | - |
| += | 加后赋值 | a += 5 | a = a + 5 |
| -= | 减后赋值 | a -= 5 | a = a - 5 |
| *= | 乘后赋值 | a *= 5 | a = a * 5 |
| /= | 除后赋值 | a /= 5 | a = a / 5 |
| %= | 取余后赋值 | a %= 5 | a = a % 5 |
java
int x = 10;
x += 5; // x = 15
x -= 3; // x = 12
x *= 2; // x = 24
x /= 4; // x = 6
x %= 5; // x = 1⚠️ 复合赋值的隐式转换:
java
byte b = 10;
// b = b + 5; // ❌ 编译错误(b + 5 是 int)
b += 5; // ✅ 正确(自动转换)
// += 等价于 b = (byte)(b + 5)📖 五、三元运算符(条件运算符)
语法:条件 ? 值1 : 值2
java
int a = 10, b = 20;
int max = a > b ? a : b; // max = 20
String result = a % 2 == 0 ? "偶数" : "奇数"; // "偶数"
// 嵌套三元运算符(不推荐,难读)
int score = 85;
String grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "D";💡 使用建议:
- 简单条件用三元运算符
- 复杂条件用 if-else(可读性更好)
📖 六、位运算符
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
| & | 按位与 | 5 & 3 | 1 |
| | | 按位或 | 5 | 3 | 7 |
| ^ | 按位异或 | 5 ^ 3 | 6 |
| ~ | 按位取反 | ~5 | -6 |
| << | 左移 | 5 << 1 | 10 |
| >> | 右移(算术) | 5 >> 1 | 2 |
| >>> | 右移(逻辑) | -5 >>> 1 | 2147483645 |
位运算详解
java
int a = 5; // 二进制:0101
int b = 3; // 二进制:0011
System.out.println(a & b); // 1 (0001)
System.out.println(a | b); // 7 (0111)
System.out.println(a ^ b); // 6 (0110)
System.out.println(~a); // -6 (取反)
System.out.println(a << 1); // 10 (左移1位 = 乘以2)
System.out.println(a >> 1); // 2 (右移1位 = 除以2)位运算应用场景
1. 乘除2的幂次:
java
int x = 16;
int y = x << 2; // x * 4 = 64(左移2位)
int z = x >> 3; // x / 8 = 2(右移3位)2. 判断奇偶:
java
int num = 7;
boolean isOdd = (num & 1) == 1; // 比 num % 2 更快3. 交换两个数(不用临时变量):
java
int a = 5, b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a = " + a + ", b = " + b); // a = 10, b = 54. 位掩码(权限管理):
java
final int READ = 1; // 0001
final int WRITE = 2; // 0010
final int EXECUTE = 4; // 0100
int permission = READ | WRITE; // 0011(读+写权限)
boolean canRead = (permission & READ) != 0; // true
boolean canExecute = (permission & EXECUTE) != 0; // false📖 七、运算符优先级
从高到低:
- 括号:
() - 一元:
++ -- ! ~ - 算术:
* / %>+ - - 移位:
<< >> >>> - 关系:
< > <= >=>== != - 位运算:
&>^>| - 逻辑:
&&>|| - 三元:
? : - 赋值:
= += -= *= /= ...
💡 最佳实践:
java
// ❌ 难以理解
int result = a + b * c > d && e || f;
// ✅ 使用括号明确优先级
int result = ((a + (b * c)) > d) && e || f;
// ✅ 更好:拆分表达式
int temp = b * c;
int sum = a + temp;
boolean condition = sum > d && e || f;🆚 Java vs C 对比
| 特性 | C 语言 | Java |
|---|---|---|
| 逻辑运算 | 0 为 false,非0 为 true | 只能用 boolean |
| 位运算 | 支持,常用 | 支持,较少用 |
| sizeof | sizeof(int) | 无(类型大小固定) |
| 指针运算 | 支持 | 不支持(无指针) |
💡 实用技巧
1. 安全的除法
java
int a = 10, b = 0;
int result = b != 0 ? a / b : 0; // 避免除零错误2. 数值交换
java
// 方法1:临时变量(推荐)
int temp = a;
a = b;
b = temp;
// 方法2:加减法
a = a + b;
b = a - b;
a = a - b;
// 方法3:异或(最高效)
a = a ^ b;
b = a ^ b;
a = a ^ b;3. 绝对值
java
int abs1 = Math.abs(x); // 标准方法
int abs2 = x < 0 ? -x : x; // 三元运算符
int abs3 = (x ^ (x >> 31)) - (x >> 31); // 位运算(最快)⚠️ 常见陷阱
陷阱1:复杂表达式副作用
java
int a = 1;
int b = a++ + ++a;这种代码虽然能运行,但可读性很差。生产代码应拆开写。
陷阱2:用 == 比较浮点数
浮点数存在精度误差,应使用误差范围比较。
java
Math.abs(a - b) < 1e-9陷阱3:忽略短路行为
短路运算右侧可能不执行,不要把必须执行的副作用放在右侧。
陷阱4:位运算优化过早
现代 JVM 会优化简单算术。为了“快”把代码写成难懂的位运算,通常得不偿失。
🧭 表达式可读性原则
写表达式时优先让人看懂。
text
条件超过两个逻辑运算,考虑拆变量。
混合 && 和 || 时加括号。
不要在条件表达式中修改变量。
位运算只在权限、掩码、底层算法中使用。
三元运算只用于简单二选一。示例:
java
boolean hasPermission = (permission & READ) != 0;
boolean validUser = user != null && user.isActive();
if (hasPermission && validUser) {
allow();
}✅ 掌握标准
学完本课后,应能做到:
text
能使用算术、关系、逻辑、赋值、三元和位运算符。
能解释前置自增和后置自增的差异。
能说明 && 和 || 的短路行为。
能用括号明确复杂表达式优先级。
能用位运算表达简单权限掩码。
能识别字符串 ==、浮点 ==、整数除法等陷阱。
能在可读性和技巧之间做正确取舍。运算符不是为了炫技,而是为了清晰表达计算和判断。复杂表达式应拆成有名字的中间变量。
📝 练习预告
完成 练习/Ex02_Operators.java:
- 算术运算综合应用
- 自增自减陷阱
- 短路运算
- 位运算实战
- 运算符优先级
- 综合:计算器程序
🎓 下一步
- 第3课:控制流 - if、switch、循环