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证明是右结合

 

 

  

posted @ 2023-04-16 19:11  为了生活更好  阅读(42)  评论(0)    收藏  举报