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