1. 什么是运算符
运算符是执行特定操作的符号。在 Java 中,运算符作用于操作数(变量或值)并产生计算结果。
java
int result = 10 + 5; // + 是运算符,10 和 5 是操作数
运算符是编程的基础工具,掌握它们才能写出高效代码。
2. 运算符介绍和使用
2.1 算术运算符
执行基本数学运算。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
+ |
加法 | 5 + 3 |
8 |
- |
减法 | 5 - 3 |
2 |
* |
乘法 | 5 * 3 |
15 |
/ |
除法 | 5 / 2 |
2 (整数除法) |
% |
取模(余数) | 5 % 2 |
1 |
++ |
自增 | i++ |
i = i + 1 |
-- |
自减 | i-- |
i = i - 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
int x = 5;
System.out.println(x++); // 5 (先用后加)
System.out.println(++x); // 7 (先加后用)
整数除法截断详解
整数相除会直接丢弃小数部分,不是四舍五入!
java
// 整数除法:直接截断小数
System.out.println(7 / 2); // 3,不是 3.5
System.out.println(9 / 4); // 2,不是 2.25
System.out.println(10 / 3); // 3,不是 3.333...
System.out.println(5 / 10); // 0,不是 0.5
// 负数除法:向零截断
System.out.println(-7 / 2); // -3,不是 -3.5
System.out.println(-9 / 4); // -2,不是 -2.25
// 如果需要小数结果,至少一个数要是浮点型
System.out.println(7.0 / 2); // 3.5
System.out.println(7 / 2.0); // 3.5
System.out.println(7.0 / 2.0);// 3.5
// 实际应用:计算平均分
int total = 250;
int count = 3;
int avg1 = total / count; // 83(截断)
double avg2 = (double)total / count; // 83.333...(精确)
取模运算详解
取模 % 返回除法的余数 ,结果的符号跟被除数一致。
计算公式 :a % b = a - (a / b) * b
java
// 正数取模
System.out.println(10 % 3); // 1
// 计算过程:10 / 3 = 3(截断),10 - 3 * 3 = 1
System.out.println(10 % -3); // 1
// 计算过程:10 / -3 = -3(截断),10 - (-3) * (-3) = 10 - 9 = 1
// 负数取模
System.out.println(-10 % 3); // -1
// 计算过程:-10 / 3 = -3(截断),-10 - (-3) * 3 = -10 - (-9) = -1
System.out.println(-10 % -3); // -1
// 计算过程:-10 / -3 = 3(截断),-10 - 3 * (-3) = -10 - (-9) = -1
规律总结:
- 结果符号只看被除数(%左边的数)
10 % 3和10 % -3结果都是1(被除数是正数)-10 % 3和-10 % -3结果都是-1(被除数是负数)
实际应用:
java
// 判断奇偶
int num = 7;
System.out.println(num % 2); // 1,奇数
num = 8;
System.out.println(num % 2); // 0,偶数
// 循环数组索引(3个元素,索引 0-2)
int index = 5;
System.out.println(index % 3); // 2,循环回到索引 2
关键点:
- 整数除法会截断小数部分(向零方向)
- 取模结果的符号跟被除数一致
++i和i++的区别在于返回值时机- 需要小数结果时,转换为
double类型
2.2 关系运算符
比较两个值,返回布尔结果。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
== |
等于 | 5 == 3 |
false |
!= |
不等于 | 5 != 3 |
true |
> |
大于 | 5 > 3 |
true |
< |
小于 | 5 < 3 |
false |
>= |
大于等于 | 5 >= 5 |
true |
<= |
小于等于 | 5 <= 3 |
false |
java
int age = 18;
System.out.println(age >= 18); // true
System.out.println(age < 16); // false
int price1 = 100;
int price2 = 100;
System.out.println(price1 == price2); // true
关系运算符不能连用
数学中的连续比较在 Java 中不能直接写,必须用逻辑运算符连接。
java
int score = 85;
// ❌ 错误写法:数学式的连续比较
// if (60 <= score <= 100) { } // 编译错误!Java 不支持
// ✅ 正确写法:拆分成两个关系运算,用 && 连接
if (score >= 60 && score <= 100) {
System.out.println("成绩有效");
}
// 再看一个例子
int age = 25;
// ❌ 错误:18 < age < 60
// boolean isAdult = 18 < age < 60; // 编译错误!
// ✅ 正确:拆分并用 && 连接
boolean isAdult = age > 18 && age < 60;
System.out.println(isAdult); // true
原理解释:
java
// 为什么不能连用?
// 假设写 10 < x < 20
// 1. 先计算 10 < x,结果是 true 或 false(布尔值)
// 2. 再计算 true < 20 或 false < 20
// 3. 但布尔值不能和数字比较,所以报错!
// 正确的写法
int x = 15;
boolean inRange = x > 10 && x < 20; // true
常见场景:
java
// 判断区间
int num = 50;
boolean between = num >= 10 && num <= 100; // [10, 100]
// 判断区间外
boolean outside = num < 10 || num > 100; // 小于10 或 大于100
// 判断成绩等级
int grade = 88;
if (grade >= 90 && grade <= 100) {
System.out.println("优秀");
} else if (grade >= 80 && grade < 90) {
System.out.println("良好");
}
关键点:
- 关系运算符返回
true或false - 不能连续比较,必须拆分成多个条件
- 用
&&(与)或||(或)连接多个关系运算(后续学习 if 语句时会大量使用)
2.3 逻辑运算符
组合多个布尔表达式。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
&& |
逻辑与(短路) | true && false |
false |
| ` | ` | 逻辑或(短路) | |
! |
逻辑非 | !true |
false |
& |
逻辑与(不短路) | true & false |
false |
| ` | ` | 逻辑或(不短路) | `true |
逻辑运算真值表
逻辑与 (&&):两个都为真,结果才为真
| A | B | A && B |
|---|---|---|
true |
true |
true |
true |
false |
false |
false |
true |
false |
false |
false |
false |
逻辑或 (||):至少一个为真,结果就为真
| A | B | A || B |
|---|---|---|
true |
true |
true |
true |
false |
true |
false |
true |
true |
false |
false |
false |
逻辑非 (!):取反
| A | !A |
|---|---|
true |
false |
false |
true |
实际应用
java
int score = 85;
boolean passed = score >= 60 && score <= 100; // true
int age = 25;
boolean discount = age < 12 || age > 65; // false
boolean isValid = !(age < 0); // true
短路 vs 非短路
短路运算符 :&& 和 ||
- 左侧能确定结果时,右侧不执行
- 提高效率,避免不必要的计算
非短路运算符 :& 和 |
- 总是计算两侧
- 主要用于位运算
实际例子
示例1:避免除零错误
java
int x = 0;
int y = 10;
// ✅ 短路:左侧 false,右侧不执行
boolean result1 = (x != 0) && (y / x > 1);
System.out.println(result1); // false,安全
// ❌ 非短路:右侧仍执行,程序崩溃
// boolean result2 = (x != 0) & (y / x > 1); // 错误!除以零
示例2:短路的执行顺序
java
int a = 5;
int b = 0;
// 短路与:左侧 false,右侧 b++ 不执行
boolean test1 = (a > 10) && (++b > 0);
System.out.println("b = " + b); // b = 0
// 非短路与:两侧都执行,b++ 会执行
boolean test2 = (a > 10) & (++b > 0);
System.out.println("b = " + b); // b = 1
示例3:短路或
java
int score = 95;
int count = 0;
// 短路或:左侧 true,右侧不执行
boolean pass1 = (score >= 90) || (++count > 0);
System.out.println("count = " + count); // count = 0
// 非短路或:两侧都执行
boolean pass2 = (score >= 90) | (++count > 0);
System.out.println("count = " + count); // count = 1
使用建议
| 场景 | 使用 | 原因 |
|---|---|---|
| 逻辑判断 | && ` |
|
| 位运算 | & ` |
` |
记忆口诀:
- 逻辑判断用双符号:
&&|| - 位运算用单符号:
&|
2.5 赋值运算符
将右边的值赋给左边的变量。
| 运算符 | 说明 | 示例 | 等价于 |
|---|---|---|---|
= |
简单赋值 | a = 5 |
- |
+= |
加后赋值 | a += 3 |
a = a + 3 |
-= |
减后赋值 | a -= 3 |
a = a - 3 |
*= |
乘后赋值 | a *= 3 |
a = a * 3 |
/= |
除后赋值 | a /= 3 |
a = a / 3 |
%= |
取模后赋值 | a %= 3 |
a = a % 3 |
java
int score = 100;
score += 10; // score = score + 10,结果 110
System.out.println(score); // 110
score -= 20; // score = score - 20,结果 90
System.out.println(score); // 90
score *= 2; // score = score * 2,结果 180
System.out.println(score); // 180
score /= 3; // score = score / 3,结果 60
System.out.println(score); // 60
score %= 7; // score = score % 7,结果 4
System.out.println(score); // 4
实际应用:
java
// 累加计数
int total = 0;
total += 10; // 10
total += 20; // 30
total += 30; // 60
// 折扣计算
int price = 100;
price -= 20; // 直接减 20,结果 80
复合赋值的隐式转换
复合赋值运算符会自动进行类型转换,而普通写法不会。
java
int num = 10;
// ✅ 复合赋值:可以,自动转换
num += 12.5; // 等价于 num = (int)(num + 12.5)
System.out.println(num); // 22(小数部分被截断)
// ❌ 普通写法:报错!
// num = num + 12.5; // 编译错误:不能将 double 赋值给 int
// 必须手动转换
num = (int)(num + 12.5); // 正确
原理解释:
java
int a = 10;
// 这两行看起来相同,但本质不同:
a += 5.5; // 编译器自动转换为:a = (int)(a + 5.5)
a = a + 5.5; // 错误!a + 5.5 结果是 double,不能直接赋给 int
// 再看一个例子
byte b = 10;
b += 200; // ✅ 可以,结果 -46(byte 溢出)
// b = b + 200; // ❌ 报错:b + 200 结果是 int,不能赋给 byte
关键点:
- 复合赋值运算符更简洁
a += 5比a = a + 5少写代码- 复合赋值会自动强制转换类型,避免编译错误
- 但要注意截断和溢出风险
2.6 位运算符
直接操作整数的二进制位。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
& |
按位与 | 5 & 3 |
1 (0101 & 0011 = 0001) |
| ` | ` | 按位或 | `5 |
^ |
按位异或 | 5 ^ 3 |
6 (0101 ^ 0011 = 0110) |
~ |
按位取反 | ~5 |
-6 (~0101 = 1010) |
位运算规则表
按位与 (&):两位都是 1,结果才是 1
| A | B | A & B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
按位或 (|):至少一位是 1,结果就是 1
| A | B | A | B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
按位异或 (^):两位不同,结果是 1;相同则是 0
| A | B | A ^ B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
按位取反 (~):0 变 1,1 变 0
| A | ~A |
|---|---|
| 0 | 1 |
| 1 | 0 |
位运算示例
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 (补码表示)
详细计算过程:
0101 (5)
& 0011 (3)
-------
0001 (1) ← 对应位都是1才是1
0101 (5)
| 0011 (3)
-------
0111 (7) ← 对应位至少一个1就是1
0101 (5)
^ 0011 (3)
-------
0110 (6) ← 对应位不同是1,相同是0
实际应用:
java
// 判断奇偶
boolean isOdd = (num & 1) == 1;
// 权限控制
int READ = 1; // 0001
int WRITE = 2; // 0010
int EXEC = 4; // 0100
int permission = READ | WRITE; // 0011
boolean canWrite = (permission & WRITE) != 0; // true
2.7 移位运算符
移动二进制位,效率高于乘除法。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
<< |
左移 | 5 << 1 |
10 (乘以2) |
>> |
右移(算术) | 5 >> 1 |
2 (除以2) |
>>> |
右移(逻辑) | -5 >>> 1 |
大正数 |
java
int x = 8;
System.out.println(x << 1); // 16 (8 * 2)
System.out.println(x << 2); // 32 (8 * 4)
System.out.println(x >> 1); // 4 (8 / 2)
System.out.println(x >> 2); // 2 (8 / 4)
int negative = -8;
System.out.println(negative >> 1); // -4 (保持符号)
System.out.println(negative >>> 1); // 2147483644 (补零)
关键点:
<<左移n位等于乘以2^n>>右移n位等于除以2^n(向下取整)>>>无符号右移,高位补0
2.8 条件运算符(三元运算符)
简洁的if-else替代方案。
语法 :条件 ? 值1 : 值2
java
int age = 20;
String type = age >= 18 ? "成年人" : "未成年人";
int a = 10, b = 20;
int max = a > b ? a : b; // 20
// 可嵌套(不推荐过度使用)
int score = 85;
String grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "D";
使用建议:
- 简单逻辑用三元运算符
- 复杂逻辑用if-else,保持可读性
3. 运算符优先级
从高到低排列:
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 1 | () [] . |
括号、数组访问、成员访问 |
| 2 | ++ -- ! ~ |
一元运算符 |
| 3 | * / % |
乘除取模 |
| 4 | + - |
加减 |
| 5 | << >> >>> |
移位 |
| 6 | < <= > >= |
关系 |
| 7 | == != |
相等性 |
| 8 | & |
按位与 |
| 9 | ^ |
按位异或 |
| 10 | ` | ` |
| 11 | && |
逻辑与 |
| 12 | ` | |
| 13 | ?: |
条件 |
| 14 | = += -= 等 |
赋值 |
java
int result = 10 + 5 * 2; // 20,不是30
int x = 5;
int y = x++ * 2; // y=10, x=6
boolean flag = 10 > 5 && 20 < 30; // true
最佳实践:
- 用括号明确意图,不依赖优先级记忆
- 复杂表达式拆分为多行
java
// 不清晰
if (a + b * c > d && e < f || g != h) { }
// 清晰
int sum = a + (b * c);
boolean condition1 = sum > d && e < f;
boolean condition2 = g != h;
if (condition1 || condition2) { }
总结
运算符是Java的基础语法,按功能分为:
- 算术:数学计算
- 关系:比较大小
- 逻辑:布尔组合
- 位:二进制操作
- 移位:高效乘除2的幂
- 条件:简化分支
掌握它们的用法和优先级,编写出简洁高效的代码。重点记住:
- 整数除法会截断
- 对象比较用
equals() &&和||会短路- 位运算用于底层优化
- 复杂表达式加括号