Skip to content

Chapter 03 · 运算符与表达式

学会用 Java 算账、比较、判断 — 编程的"加减乘除"全在这一章。


🎯 本章目标

  • 掌握 Java 的 算术、赋值、比较、逻辑、位、三元 运算符
  • 理解 运算符优先级结合性
  • 写得出 短路求值、避开整数除法、自增自减坑
  • 知道 位运算 在工程中的实际用途

1. 运算符总览

Java 运算符全景

把 Java 的运算符按"用途"分成 6 大类,记忆的时候按类来记,比一个个背强多了。


2. 算术运算符(最熟悉的一类)

运算符含义例子结果
+加 / 字符串拼接1 + 2 "a"+"b"3 "ab"
-5 - 32
*4 * 28
/7 / 23(整数除法!)
%取余 / 取模7 % 21
++自增 1i++++i见下方
--自减 1i----i见下方

整数除法的坑

java
int a = 7;
int b = 2;
System.out.println(a / b);      // 3,不是 3.5
System.out.println(a / 2.0);    // 3.5,只要有一个是浮点就 OK
System.out.println((double) a / b); // 3.5

💡 生活类比:分糖果。7 颗糖分给 2 个小朋友,每人 3 颗(7/2=3),剩 1 颗放回(7%2=1)。这就是整除和取模。

自增自减:i++ vs ++i

java
int i = 5;
int a = i++;    // 先赋值再自增:a = 5,i = 6
int b = ++i;    // 先自增再赋值:i = 7,b = 7

口诀:++ 在前先算后用,++ 在后先用后算。

🚨 面试坑题

java
int x = 1;
x = x++;     // 猜猜 x 是几?

答:1!因为 x++ 先取值 1 备用,再让 x 自增成 2,最后把"备用的 1"赋值回 x。


3. 赋值运算符

运算符等价形式
=赋值
+=a = a + b
-=a = a - b
*=a = a * b
/=a = a / b
%=a = a % b

🤓 隐藏特性:复合赋值 += 等内置了强制类型转换:

java
short s = 10;
s = s + 1;    // ❌ 编译错误(int 不能直接给 short)
s += 1;       // ✅ 编译通过!等价于 s = (short)(s + 1)

4. 比较运算符(结果是 boolean)

运算符含义例子
==等于(基本类型比值,引用类型比地址)a == b
!=不等于a != b
> <大于 / 小于5 > 3
>= <=大于等于 / 小于等于a >= 18

字符串千万别用 ==

java
String a = "hello";
String b = new String("hello");
System.out.println(a == b);          // false  ❌
System.out.println(a.equals(b));     // true   ✅

口诀比内容用 equals,比身份用 ==


5. 逻辑运算符(连接 boolean 表达式)

运算符含义短路例子
&&与(and)age >= 18 && age <= 60
||或(or)isVip || points > 1000
!非(not)-!isFinished
&不短路与两边都会执行
|不短路或两边都会执行

短路求值是什么?

java
int x = 0;
if (x != 0 && 10 / x > 1) {  // x != 0 为 false,&& 后面直接跳过
    // ...
}
// 用 & 就会爆炸:if (x != 0 & 10/x > 1) → ArithmeticException

短路求值原理

💡 生活类比:去吃饭看 A 大众点评 4.5 分以上 && B 评论数大于 100。如果 A 已经不满足,B 看都不用看,直接走人。这就是短路。


6. 位运算符(高阶选修,但面试常考)

运算符含义例子二进制
&按位与5 & 3 = 1101 & 011 = 001
|按位或5 | 3 = 7101 | 011 = 111
^按位异或(不同为 1)5 ^ 3 = 6101 ^ 011 = 110
~按位取反~5 = -6二补码取反
<<左移5 << 1 = 10等于 ×2
>>右移(带符号)5 >> 1 = 2等于 ÷2
>>>无符号右移高位补 0用于 hash

工程中真实用途

  1. 快速 ×2 / ÷2x << 1x * 2 略快(极少需要这么抠)
  2. 判断奇偶(n & 1) == 0 判断偶数
  3. 权限位操作:用一个 int 存多个开关
  4. HashMap 计算下标hash & (length - 1)
  5. 交换两数(不用临时变量)a ^= b; b ^= a; a ^= b;
java
// 例:用一个 int 存四个权限
final int READ    = 1;     // 0001
final int WRITE   = 2;     // 0010
final int EXECUTE = 4;     // 0100
final int DELETE  = 8;     // 1000

int permission = READ | WRITE;          // 既能读又能写
boolean canRead  = (permission & READ) != 0;
boolean canDelete = (permission & DELETE) != 0; // false

7. 三元运算符(条件运算符)

简洁版 if-else,只能写一行:

java
int score = 85;
String grade = score >= 60 ? "及格" : "不及格";

// 等价于
String g;
if (score >= 60) g = "及格";
else g = "不及格";

可以嵌套,但不要超过 2 层(不然没人看得懂):

java
String level = score >= 90 ? "优"
             : score >= 80 ? "良"
             : score >= 60 ? "中"
             : "差";

8. 运算符优先级(不用全记,关键时加括号)

运算符优先级

记忆技巧:高层级 → 低层级:

  1. 后缀x++ x--
  2. 一元! ~ ++x
  3. 算术* / % > + -
  4. 移位<< >> >>>
  5. 比较< <= > >= instanceof == !=
  6. 位运算& > ^ > |
  7. 逻辑&& > ||
  8. 三元? :
  9. 赋值= += -= ...

💡 实战建议:除了 * + - / 这种基础的,其他全部 加括号 让代码意图明确,省得你和审代码的同事吵架。


9. 实战练习

文件内容
OperatorDemo.java各类运算符演示
AutoIncrementPitfall.javai++ vs ++i 经典面试题
BitOperationDemo.java位运算实际应用
PermissionSystem.java用位运算实现权限系统

10. 浏览器演示

打开 demo.html

  • 运算符在线计算器
  • 短路求值动画演示
  • 二进制位运算可视化

11. 面试可能会问什么?

Q1: a == ba.equals(b) 有什么区别?

  • == 比较 值(基本类型)引用地址(引用类型)
  • .equals() 默认与 == 等价(Object 类的实现),但 String、Integer 等类 重写 了 equals,比较的是 内容

Q2: i++++i 的区别?

  • i++:先取值,后自增
  • ++i:先自增,再取值
java
int i = 5;
int a = i++;  // a=5, i=6
int b = ++i;  // i=7, b=7

Q3: 解释 int x = 1; x = x++; 的结果

:x 还是 1。

  • 等价于 int tmp = x; x = x + 1; x = tmp;
  • 最终 x 被赋值回 1。

Q4: &&& 有什么区别?

对比&&&
短路
类型仅 booleanboolean 或位运算
性能短路时更快始终算两侧
安全防 NPE/除零可能触发异常

Q5: 0.1 + 0.2 == 0.3 是 true 吗?

:false。浮点二进制表示问题。详见 Chapter 02。

Q6: 怎么不用临时变量交换两个 int?

java
int a = 3, b = 5;
a = a ^ b;
b = a ^ b;   // b = (a^b)^b = a
a = a ^ b;   // a = (a^b)^a = b
// 现在 a=5, b=3

⚠️ 实际工程不推荐这样写,可读性差,编译器优化后正常写法一样快。

Q7: 为什么 HashMap 用 hash & (length-1) 而不是 hash % length

:当 length 是 2 的幂时,hash & (length-1) 等价于 hash % length,但 位运算比取模快得多。这是 HashMap 强制 length 必须是 2 的幂的原因之一。

Q8: >>>>> 的区别?

  • >> 算术右移:高位补符号位(正数补 0,负数补 1)
  • >>> 逻辑右移:高位永远补 0
java
int n = -8;          // 二进制: 1111...1000
System.out.println(n >> 2);   // -2 (高位补 1)
System.out.println(n >>> 2);  // 1073741822 (高位补 0)

🎁 本章小结

✅ 6 类运算符:算术、赋值、比较、逻辑、位、三元
✅ 字符串比较只能用 .equals()
✅ && || 短路求值,能避免 NPE 和除零
✅ 位运算用于权限、HashMap、性能场景
✅ 实在记不住优先级,加括号最稳

🔗 导航