07_表达式优先级与括号应用
一、表达式优先级概述
在 Java 中,表达式由运算符、操作数和括号组成,运算符的优先级决定了表达式中运算的执行顺序。如果不明确优先级,可能导致程序逻辑错误或结果不符合预期。
优先级的核心规则:
- 优先级高的运算符先执行
- 优先级相同的运算符按结合性(从左到右或从右到左)执行
- 括号可以改变默认的优先级顺序
二、运算符优先级总表(从高到低)
| 优先级 | 运算符 | 描述 | 结合性 |
|---|---|---|---|
| 1 | ()、[]、. | 括号、数组访问、成员访问 | 从左到右 |
| 2 | ++、--(后缀) | 自增、自减(后置) | 从左到右 |
| 3 | ++、--(前缀)、+、-(单目)、~、! | 自增、自减(前置)、正负号、按位取反、逻辑非 | 从右到左 |
| 4 | *、/、% | 乘法、除法、取余 | 从左到右 |
| 5 | +、-(双目) | 加法、减法 | 从左到右 |
| 6 | <<、>>、>>> | 左移、右移、无符号右移 | 从左到右 |
| 7 | <、<=、>、>=、instanceof | 关系运算符、类型判断 | 从左到右 |
| 8 | ==、!= | 等于、不等于 | 从左到右 |
| 9 | & | 按位与 | 从左到右 |
| 10 | ^ | 按位异或 | 从左到右 |
| 11 | | | 按位或 | 从左到右 |
| 12 | && | 逻辑与 | 从左到右 |
| 13 | || | 逻辑或 | 从左到右 |
| 14 | ? : | 三元运算符 | 从右到左 |
| 15 | =、+=、-=、*=、/=等 | 赋值运算符 | 从右到左 |
三、优先级规则详解
3.1 最高优先级:括号与成员访问
- ():改变运算顺序,或作为方法调用的标志
- []:数组元素访问
- .:对象成员访问(属性或方法)
int result = (10 + 20) * 3; // 括号改变顺序,先算10+20
String name = user.getName(); // .运算符访问对象方法
int value = arr[0]; // []访问数组元素
3.2 单目运算符(优先级 3)
单目运算符只需要一个操作数,优先级高于双目运算符:
int a = 5;
int b = -a; // 单目减,等价于 b = -(a)
int c = ~a; // 按位取反,优先级高于算术运算符
boolean d = !true; // 逻辑非
3.3 算术运算符(优先级 4-5)
- 先乘除取余(*、/、%),后加减(+、-)
int result = 10 + 20 * 3; // 先算20*3=60,再算10+60=70
int remainder = 10 % 3 + 2; // 先算10%3=1,再算1+2=3
3.4 关系与逻辑运算符(优先级 7-13)
- 关系运算符(<、>等)优先级高于逻辑运算符
- 逻辑与(&&)优先级高于逻辑或(||)
boolean flag = 5 > 3 && 2 < 1; // 先算5>3=true和2<1=false,再算true && false=false
boolean result = 10 == 10 || 5 > 10 && 3 < 1; // 等价于 10==10 || (5>10 && 3<1)
3.5 三元运算符与赋值运算符(优先级 14-15)
- 三元运算符(? :)优先级高于赋值运算符
- 赋值运算符优先级最低,结合性为从右到左
int a, b;
a = b = 10; // 从右到左:先b=10,再a=b
int max = a > b ? a : b; // 三元运算符优先级高于赋值
四、结合性规则
结合性指当多个优先级相同的运算符连续出现时的执行顺序:
4.1 从左到右(大多数运算符)
int result = 10 + 20 + 30; // 等价于 (10 + 20) + 30
int remainder = 100 % 10 / 2; // 等价于 (100 % 10) / 2
4.2 从右到左(少数运算符)
- 单目运算符(如++前缀、!)
- 三元运算符(? :)
- 赋值运算符(=、+=等)
int a = 5;
int b = ++a; // 从右到左:先a自增为6,再赋值给b
int c = 1 > 2 ? 3 : 4 > 5 ? 6 : 7; // 等价于 1>2 ? 3 : (4>5 ? 6 :7)
五、括号的应用
5.1 改变默认优先级
括号可以强制改变运算顺序,忽略默认优先级:
// 默认顺序:先乘除后加减
int defaultOrder = 10 + 20 * 3; // 70
// 括号改变顺序:先加减后乘除
int changedOrder = (10 + 20) * 3; // 90
5.2 提高代码可读性
即使不改变顺序,括号也能让逻辑更清晰:
// 可读性差
boolean complex = a > b && c < d || e == f;
// 可读性好(明确分组)
boolean clear = (a > b && c < d) || (e == f);
5.3 嵌套括号的执行顺序
括号可以嵌套,内层括号优先执行:
int nested = ((1 + 2) * 3 - 4) / 5;
// 执行顺序:1+2=3 → 3*3=9 → 9-4=5 → 5/5=1
六、常见错误与解决方案
6.1 忽略单目运算符的高优先级
错误示例:
int a = 5;
int b = -a++; // 预期:-(a++) → -5,但实际执行顺序为 -(a++)
System.out.println(b); // 输出-5(正确),但逻辑易误解
解决方案:用括号明确逻辑
int b = -(a++); // 明确表示先自增再取负
6.2 逻辑运算符优先级混淆
错误示例:
boolean flag = 1 > 2 || 3 > 2 && 5 < 4;
// 错误理解:(1>2 || 3>2) && 5<4 → false
// 实际执行:1>2 || (3>2 && 5<4) → false || (true && false) → false
解决方案:添加括号明确分组
boolean flag = (1 > 2 || 3 > 2) && 5 < 4; // 明确逻辑
6.3 赋值运算符结合性错误
错误示例:
int a, b = 10; // 仅b被初始化,a未初始化
if (a = b) { // 编译错误:赋值表达式结果为int,不能作为boolean条件
// ...
}
解决方案:区分=和==,正确初始化变量
int a = 0, b = 10; // 初始化a
if (a == b) { // 用==判断相等
// ...
}
6.4 三元运算符嵌套过深
错误示例:
int result = a > b ? c > d ? c : d : e > f ? e : f;
解决方案:拆分或用括号明确层次
int temp = c > d ? c : d;
int result = a > b ? temp : (e > f ? e : f);
七、最佳实践
- 优先使用括号:当对优先级不确定时,用括号明确顺序,避免依赖记忆
- 控制表达式复杂度:复杂表达式拆分为多个简单表达式,提高可读性
- 避免过度嵌套:括号嵌套不超过 3 层,否则拆分代码
- 明确逻辑分组:即使优先级明确,也可通过括号突出逻辑分组
- 测试验证:对复杂表达式,通过输出中间结果验证执行顺序
// 推荐写法:清晰、易维护
int sum = a + b;
int product = c * d;
int finalResult = (sum + product) / 2;
八、总结
- 优先级决定执行顺序:高优先级运算符先执行,同优先级按结合性执行
- 括号的双重作用:改变默认优先级和提高代码可读性
- 常见陷阱:单目运算符优先级、逻辑运算符顺序、赋值与相等判断混淆
- 最佳实践:优先使用括号,拆分复杂表达式,明确逻辑分组
掌握表达式优先级规则并合理使用括号,是编写正确、清晰 Java 代码的基础,能有效避免因运算顺序错误导致的逻辑 bug。

浙公网安备 33010602011771号