一 先看下面的一段代码
int a = 0,b = 1;
a = b++;
System.out.println("a=" + a + " b=" + b);
结果 : a = 1 , b = 2;
so easy是吧,那么下面的代码呢
int b = 1;
b = b++;
System.out.println(" b=" + b);
安照以前的想法,后++先赋值再运算。b赋值给b,那么b是1,b然后再加加变成2。但实际结果呢b = 1。这个时候用以前的解释就不行了,那么我们只能从字节码的角度来看看。(字节码是什么?哥你一定不是搞java的)
字节码 - 通过使用 " javap -verbose字节码文件名 "
Last modified 2019-2-25; size 625 bytes
MD5 checksum cd686906c6f2122f202bade4da32df69
Compiled from "Test3.java"
public class Test3
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #11.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #21.#22 // java/lang/System.out:Ljava/io/Print
Stream;
#3 = Class #23 // java/lang/StringBuilder
#4 = Methodref #3.#20 // java/lang/StringBuilder."<init>":()
V
#5 = String #24 // b=
#6 = Methodref #3.#25 // java/lang/StringBuilder.append:(Lja
va/lang/String;)Ljava/lang/StringBuilder;
#7 = Methodref #3.#26 // java/lang/StringBuilder.append:(I)L
java/lang/StringBuilder;
#8 = Methodref #3.#27 // java/lang/StringBuilder.toString:()
Ljava/lang/String;
#9 = Methodref #28.#29 // java/io/PrintStream.println:(Ljava/
lang/String;)V
#10 = Class #30 // Test3
#11 = Class #31 // java/lang/Object
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 main
#17 = Utf8 ([Ljava/lang/String;)V
#18 = Utf8 SourceFile
#19 = Utf8 Test3.java
#20 = NameAndType #12:#13 // "<init>":()V
#21 = Class #32 // java/lang/System
#22 = NameAndType #33:#34 // out:Ljava/io/PrintStream;
#23 = Utf8 java/lang/StringBuilder
#24 = Utf8 b=
#25 = NameAndType #35:#36 // append:(Ljava/lang/String;)Ljava/la
ng/StringBuilder;
#26 = NameAndType #35:#37 // append:(I)Ljava/lang/StringBuilder;
#27 = NameAndType #38:#39 // toString:()Ljava/lang/String;
#28 = Class #40 // java/io/PrintStream
#29 = NameAndType #41:#42 // println:(Ljava/lang/String;)V
#30 = Utf8 Test3
#31 = Utf8 java/lang/Object
#32 = Utf8 java/lang/System
#33 = Utf8 out
#34 = Utf8 Ljava/io/PrintStream;
#35 = Utf8 append
#36 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#37 = Utf8 (I)Ljava/lang/StringBuilder;
#38 = Utf8 toString
#39 = Utf8 ()Ljava/lang/String;
#40 = Utf8 java/io/PrintStream
#41 = Utf8 println
#42 = Utf8 (Ljava/lang/String;)V
{
public Test3();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>
":()V
4: return
LineNumberTable:
line 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: iconst_1
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: getstatic #2 // Field java/lang/System.out:Ljav
a/io/PrintStream;
10: new #3 // class java/lang/StringBuilder
13: dup
14: invokespecial #4 // Method java/lang/StringBuilder.
"<init>":()V
17: ldc #5 // String b=
19: invokevirtual #6 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: iload_1
23: invokevirtual #7 // Method java/lang/StringBuilder.
append:(I)Ljava/lang/StringBuilder;
26: invokevirtual #8 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
29: invokevirtual #9 // Method java/io/PrintStream.prin
tln:(Ljava/lang/String;)V
32: return
LineNumberTable:
line 4: 0
line 6: 2
line 8: 7
line 9: 32
}
SourceFile: "Test3.java"
这么多怎么看?难道我再去学字节码文件内容都表示什么意思?no no no这样学习得学到什么时候,所以咱们看下面的重点。第7行以后开始是输出语句,咱们就不用关心了。
int b = 1
b = b++;
---------------------------执行的代码-----------------------------
Code:
stack=3, locals=2, args_size=1
0: iconst_1 //将常量1压入栈中
1: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
2: iload_1 //将本地变量表中第1个位置的数据取出放入栈顶中
3: iinc 1, 1 //将本地变量表中第1个位置的变量加1
6: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
我们发现,后++ : 先将本地变量表中的值取出放入栈中,自身加1,再将栈中的值取回进行覆盖
再看下第一个代码的字节码文件
int a = 0,b = 1;
a = b++;
System.out.println("a=" + a + " b=" + b);
----------------------------------------------------
0: iconst_0 //将0压入栈中
1: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
2: iconst_1 //将1压入栈中
3: istore_2 //将栈顶出栈赋值给本地变量表中第2个位置的变量中
4: iload_2 //将本地变量表中的第2个位置的变量取出,放入栈顶
5: iinc 2, 1 //将本地变量表中第2个位置加1
8: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
总结 : a= b++ 先将本地变量表中的b的值取出放入到栈中,本地变量表中的b进行加1操作,再将栈中的值取出赋值给,需要赋值的那个变量(a)。
------------------------------------------- 前++ --------------------------------------------------
int a = 0,b = 1;
a = ++b;
System.out.println("a=" + a + " b=" + b);
结果 : a = 2, b = 2;
Code:
stack=3, locals=3, args_size=1
0: iconst_0 //将0压入栈中
1: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
2: iconst_1 //将1压入栈中
3: istore_2 //将栈顶出栈赋值给本地变量表中第2个位置的变量中
4: iinc 2, 1 //将本地变量表中第2个位置加1
7: iload_2 //将本地变量表中的第2个位置的变量取出,放入栈顶
8: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
再看下面的代码
int b = 1;
b = ++b;
System.out.println(" b=" + b);
-------------------------------------------------------
Code:
stack=3, locals=2, args_size=1
0: iconst_1 //将1压入栈中
1: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
2: iinc 1, 1 //将本地变量表中第1个位置加1
5: iload_1 //将本地变量表中的第1个位置的变量取出,放入栈顶
6: istore_1 //将栈顶出栈赋值给本地变量表中第1个位置的变量中
总结 b = a++ : 先将本地变量中所在位置的a变量做加1的操作,再将该值取出放入到栈顶,再将栈中的值取出赋值给,需要赋值的那个变量(a)。