Java基础系列之:一篇搞懂前++和后++的区别(上)

一 先看下面的一段代码

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)。

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值