Java深入学习17:从字节码指令角度理解i++和++i

Java深入学习17:从字节码指令角度理解i++和++i

一、先看一段代码

public class AutoIncrementTest {

    public static void main(String[] args) {
        int i =  1;
        i = i++;
        int j = i++;
        int k = i + ++i * i++;
        System.out.println("i = " + i);//i = 4
        System.out.println("j = " + j);//j = 1
        System.out.println("k = " + k);//k = 11 (2 + 3 * 3)
    }

}

二、从字节码指令角度理解i++和++i

        //i++ 和 ++i 的区别,从字节码指令角度,
        //比如int a = b;逻辑是,将局部变量b的值入栈,将入栈的值赋给a;
        //那么 int a = b++,表示局部变量b值先入栈,再b本身自增(但不影响入栈的b值),将入栈的值赋给a;
        //那么 int a = ++b,表示局部变量b值本身先自增,自增后的b值入栈,将入栈的值赋给a;

三、代码字节码解释

    public class interview.AutoIncrementTest {
  public interview.AutoIncrementTest();
        Code:
        0: aload_0
        1: invokespecial #1                  // Method java/lang/Object."<init>":()V
        4: return

        public static void main(java.lang.String[]);
        Code:

        // int i = 1
        0: iconst_1     // 1(int)值入栈
        1: istore_1     // 将栈顶int类型值保存到局部变量1中

        //i = i++
        2: iload_1      //从局部变量1中装载int类型值入栈。
        3: iinc          1, 1       //将整数值constbyte加到indexbyte指定的int类型的局部变量中(1,1表示1加到变量1中)
        6: istore_1     //将栈顶int类型值保存到局部变量1中

        //int j = i++;
        7: iload_1      //从局部变量1中装载int类型值入栈
        8: iinc          1, 1       //将整数值constbyte加到indexbyte指定的int类型的局部变量中(1,1表示1加到变量1中)
        11: istore_2    //将栈顶int类型值保存到局部变量2中

        int k = i + ++i * i++;
        //i
        12: iload_1     //从局部变量1中装载int类型值入栈
        //++i
        13: iinc          1, 1       //将整数值constbyte加到indexbyte指定的int类型的局部变量中(1,1表示1加到变量1中)
        16: iload_1     //从局部变量1中装载int类型值入栈
        //i++
        17: iload_1     //从局部变量1中装载int类型值入栈
        18: iinc          1, 1       //将整数值constbyte加到indexbyte指定的int类型的局部变量中(1,1表示1加到变量1中)
        21: imul        //将栈顶两int类型数相乘,结果入栈
        22: iadd        //将栈顶两int类型数相加,结果入栈
        23: istore_3        //将栈顶int类型值保存到局部变量3中

        //以下略
        24: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        27: new           #3                  // class java/lang/StringBuilder
        30: dup
        31: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        34: ldc           #5                  // String i =
        36: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        39: iload_1
        40: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        43: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        46: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        49: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        52: new           #3                  // class java/lang/StringBuilder
        55: dup
        56: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        59: ldc           #10                 // String j =
        61: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        64: iload_2
        65: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        68: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        71: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        74: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        77: new           #3                  // class java/lang/StringBuilder
        80: dup
        81: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        84: ldc           #11                 // String k =
        86: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        89: iload_3
        90: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        93: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        96: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        99: return
    }

四、附: IDE使用javap查看字节码,文章参考:https://blog.csdn.net/qq_41618510/article/details/84669443

主要设置如下

END

原文地址:https://www.cnblogs.com/wobuchifanqie/p/12604980.html