Java 完全指南 / 05 - 运算符:算术、逻辑、位运算、三元
05 - 运算符:算术、逻辑、位运算、三元
算术运算符
| 运算符 |
名称 |
示例 |
结果 |
+ |
加 |
10 + 3 |
13 |
- |
减 |
10 - 3 |
7 |
* |
乘 |
10 * 3 |
30 |
/ |
除 |
10 / 3 |
3(整数除法截断) |
% |
取模 |
10 % 3 |
1 |
++ |
自增 |
i++ / ++i |
i = i + 1 |
-- |
自减 |
i-- / --i |
i = i - 1 |
public class ArithmeticDemo {
public static void main(String[] args) {
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
// 浮点除法
double da = 10.0, db = 3.0;
System.out.println("浮点除法: " + (da / db)); // 3.3333...
// 自增前缀 vs 后缀
int x = 5;
int y = x++; // y = 5, x = 6(先赋值后自增)
int z = ++x; // z = 7, x = 7(先自增后赋值)
System.out.println("x=" + x + ", y=" + y + ", z=" + z);
// 整数溢出
int max = Integer.MAX_VALUE; // 2147483647
System.out.println("溢出: " + (max + 1)); // -2147483648
// 除以零
// int div = 10 / 0; // ❌ ArithmeticException
double d = 10.0 / 0.0; // ✅ Infinity(不会抛异常)
System.out.println("浮点除零: " + d); // Infinity
}
}
赋值运算符
| 运算符 |
等价于 |
示例 |
= |
- |
a = 10 |
+= |
a = a + b |
a += 5 |
-= |
a = a - b |
a -= 3 |
*= |
a = a * b |
a *= 2 |
/= |
a = a / b |
a /= 4 |
%= |
a = a % b |
a %= 3 |
&= |
a = a & b |
a &= 0xFF |
|= |
a = a | b |
a |= 0x01 |
^= |
a = a ^ b |
a ^= mask |
<<= |
a = a << n |
a <<= 2 |
>>= |
a = a >> n |
a >>= 1 |
⚠️ 复合赋值运算符会自动进行类型转换:byte b = 10; b += 5; 等价于 b = (byte)(b + 5);
比较运算符
| 运算符 |
含义 |
示例 |
== |
等于 |
a == b |
!= |
不等于 |
a != b |
> |
大于 |
a > b |
< |
小于 |
a < b |
>= |
大于等于 |
a >= b |
<= |
小于等于 |
a <= b |
instanceof |
类型检查 |
obj instanceof String |
public class ComparisonDemo {
public static void main(String[] args) {
// 基本类型:比较值
int a = 10, b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
// 包装类陷阱
Integer x = 128, y = 128;
System.out.println(x == y); // false!(比较引用)
System.out.println(x.equals(y)); // true(比较值)
// 字符串比较
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false(不同对象)
System.out.println(s1.equals(s2)); // true(值相等)
System.out.println("hello" == "hello"); // true(字面量共享)
// instanceof(JDK 16+ 模式匹配)
Object obj = "Hello";
if (obj instanceof String s) {
System.out.println("长度: " + s.length()); // 无需强转
}
}
}
逻辑运算符
| 运算符 |
含义 |
特点 |
&& |
短路与 |
左侧为 false 时,右侧不执行 |
|| |
短路或 |
左侧为 true 时,右侧不执行 |
! |
逻辑非 |
取反 |
& |
逻辑与 |
两侧都执行 |
| |
逻辑或 |
两侧都执行 |
^ |
逻辑异或 |
不同为 true |
public class LogicDemo {
public static void main(String[] args) {
// 短路求值
int x = 0;
// if (x != 0 && 10 / x > 1) { ... } // 安全,短路
// if (x != 0 & 10 / x > 1) { ... } // ❌ ArithmeticException!
// 三元运算符
int score = 85;
String grade = score >= 60 ? "及格" : "不及格";
System.out.println(grade); // 及格
// 嵌套三元(不推荐太深)
String level = score >= 90 ? "优秀"
: score >= 80 ? "良好"
: score >= 60 ? "及格"
: "不及格";
System.out.println(level); // 良好
}
}
位运算符
| 运算符 |
名称 |
示例 |
说明 |
& |
按位与 |
0b1100 & 0b1010 = 0b1000 |
都为 1 才为 1 |
| |
按位或 |
0b1100 | 0b1010 = 0b1110 |
有 1 就为 1 |
^ |
按位异或 |
0b1100 ^ 0b1010 = 0b0110 |
不同为 1 |
~ |
按位取反 |
~0b1100 = ...0011 |
0 变 1,1 变 0 |
<< |
左移 |
1 << 3 = 8 |
左移 n 位 = ×2ⁿ |
>> |
右移(带符号) |
-8 >> 2 = -2 |
高位补符号位 |
>>> |
无符号右移 |
-1 >>> 28 |
高位补 0 |
public class BitwiseDemo {
public static void main(String[] args) {
int a = 0b11001010; // 202
int b = 0b10101100; // 172
System.out.println("a & b = " + Integer.toBinaryString(a & b)); // 10001000
System.out.println("a | b = " + Integer.toBinaryString(a | b)); // 11101110
System.out.println("a ^ b = " + Integer.toBinaryString(a ^ b)); // 01100110
System.out.println("~a = " + Integer.toBinaryString(~a));
// 位移运算
System.out.println("1 << 4 = " + (1 << 4)); // 16
System.out.println("16 >> 2 = " + (16 >> 2)); // 4
// 实际应用:权限标志
final int READ = 0b001; // 1
final int WRITE = 0b010; // 2
final int EXECUTE = 0b100; // 4
int permission = READ | WRITE; // 赋予读写权限
System.out.println("有读权限: " + ((permission & READ) != 0)); // true
System.out.println("有执行权限: " + ((permission & EXECUTE) != 0)); // false
// 切换权限
permission ^= EXECUTE; // 添加执行权限
permission ^= READ; // 移除读权限
System.out.println("最终权限: " + Integer.toBinaryString(permission)); // 110
}
}
位运算实用技巧
public class BitTricks {
public static void main(String[] args) {
// 判断奇偶(比 % 2 快)
int n = 7;
System.out.println((n & 1) == 0 ? "偶数" : "奇数");
// 乘除 2 的幂
System.out.println(5 << 1); // 10(×2)
System.out.println(5 << 3); // 40(×8)
System.out.println(40 >> 3); // 5(÷8)
// 不用临时变量交换两个数
int x = 3, y = 7;
x ^= y; y ^= x; x ^= y;
System.out.println("x=" + x + ", y=" + y); // x=7, y=3
// 求绝对值(不考虑溢出)
int val = -42;
int abs = (val ^ (val >> 31)) - (val >> 31);
System.out.println("绝对值: " + abs); // 42
}
}
运算符优先级
| 优先级 |
运算符 |
结合性 |
| 1 |
() [] . |
左 → 右 |
| 2 |
! ~ ++ -- +(正) -(负) |
右 → 左 |
| 3 |
* / % |
左 → 右 |
| 4 |
+ - |
左 → 右 |
| 5 |
<< >> >>> |
左 → 右 |
| 6 |
< <= > >= instanceof |
左 → 右 |
| 7 |
== != |
左 → 右 |
| 8 |
& |
左 → 右 |
| 9 |
^ |
左 → 右 |
| 10 |
| |
左 → 右 |
| 11 |
&& |
左 → 右 |
| 12 |
|| |
左 → 右 |
| 13 |
? : |
右 → 左 |
| 14 |
= += -= 等 |
右 → 左 |
💡 记忆口诀:单目 > 算术 > 移位 > 关系 > 位运算 > 逻辑 > 三元 > 赋值。拿不准就加括号!
⚠️ 注意事项
- 整数溢出不抛异常 — Java 整数溢出会默默回绕,使用
Math.addExact() 等方法可检测溢出。
- 浮点数不能用
== 比较 — 使用 Math.abs(a - b) < 1e-9 或 Double.compare()。
>>> 是 Java 特有的 — 其他语言可能没有无符号右移操作符。
- 字符串拼接使用
+ — 编译器会优化为 StringBuilder,但循环中应手动使用 StringBuilder。
💡 技巧
-
检查 2 的幂:
boolean isPowerOfTwo = (n & (n - 1)) == 0 && n > 0;
-
位计数:
int bitCount = Integer.bitCount(0b10101010); // 4
-
数字中 1 的个数(Brian Kernighan 算法):
int count = 0;
int n = 0b10101010;
while (n != 0) { n &= (n - 1); count++; }
🏢 业务场景
- 权限系统: 使用位运算实现 RBAC 权限管理,每个 bit 代表一种权限。
- 分布式 ID: Snowflake 算法使用位移运算组合时间戳、机器 ID、序列号。
- 网络编程: 子网掩码计算大量使用位运算。
📖 扩展阅读