Java运算符优先级分析
package com.zt.javase01;
public class Test2 {
public static void main(String[] args) {
int n = 10;
n += (n++) + (++n);
System.out.println(n);//输出32
/*
(n++) (++n)
从左到右执行
因此(n++)表达式的值10 n的值变为了11
(++n) 的表达式的值变为了12 n的值变为了12
+ (n++)+(++n)整个表达式的值变为了22
+= n+=的这个n不好分析, 要分析得从操作数栈和局部变量表的角度
*/
/*
*
字节码分析 下面是用javap反编译class得到的字节码指令指令
方法执行时栈有局部变量表和操作数栈区域, 局部变量表一般存储变量, 操作数栈是用来运算的, 但是i++和==i对应的inc指令可以不通过操作数栈直接为局部变量自增
javap -c com.zt.javase01.Test2
Compiled from "Test2.java"
public class com.zt.javase01.Test2 {
public com.zt.javase01.Test2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10 //将10压到操作数栈 此时栈中数据为10
2: istore_1 //从操作数栈中弹出10保存到局部变量表第1个槽位 int n = 10;
3: iload_1 //从局部变量表取10 取到操作数栈 此时栈中数据 10 n+=的n入操作数栈
4: iload_1 //从局部变量表取10 到操作数栈 此时栈中数据 10 10 n++的n入操作数栈
5: iinc 1, 1 //局部变量表中第1槽的值自增1变为11 n++
8: iinc 1, 1 //局部变量表中第1槽的值自增1变为12 ++n
11: iload_1 //从局部变量表中取值12到操作数栈 此时栈中数据 12 10 10 ++n的n入操作数栈
12: iadd //求和 从栈中弹出12 10求和并压到栈顶 也就是现在栈变成了 22 10 求(n++)和(++n)的值
13: iadd //弹出22和12 求和 得到32
14: istore_1 // 从操作数栈弹出32放到局部变量表1的位置
15: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; //获取对象
18: iload_1 //从局部变量表读取数值32
19: invokevirtual #3 // Method java/io/PrintStream.println:(I)V //打印
22: return
}
Process finished with exit code 0
*
* */
}
}
字节码指令官方文档:
https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.iload_n
关于运算符的结合性
a 运算符1 b 运算符2 c
结合性不是决定运算符1和运算符2哪个先计算
而是决定了运算符优先级相同时 表达式实际是
(a 运算符1 b) 运算符2 c
还是
a 运算符1 (b 运算符c)
例如
int x=100, y=0;
int result= x > y ? 100 : ++y > 2 ? 20 : 30;
上面表达式如果条件运算符是右结合那相当于下面的表达式
x>y?100: (++y>2?20:30) 结果为100
如果条件运算符是左结合相当于下面的表达式
(x>y?100:++y) >2?20:30 结果为20
最终执行代码验证
System.out.println(result);
输出100证明是右结合

浙公网安备 33010602011771号