java中a 和 a_Java中a=a++ 和 a=++a(轉)

轉自https://blog.csdn.net/lovepluto/article/details/81062176

如果問 a++ 和 ++a 的區別,估計很多都能回答上來。a++ 是先取 a 的值再自增 。而 ++a 剛好相反,是先自增再取 a 的值。這里有點編程基礎都可以理解,不做過多解釋,但在 Java 里面事情就真的這么簡單嗎?

int a = 1;

a = a++;

System.out.println(a);

憑借自己所學,在不測試的情況下,你能給出答案嗎?

第一次看見這個問題的時候,想當然的認為答案是:2。但殘酷的事實告訴我,答案是:1。當時面對這個結果我是無法接受的,網上瘋狂搜索這個答案的解釋。限於當時知識的水平,只記住了這個結論,至於推導這個結論那些指令,一個也不能理解。今天看書遇見數據操作,就又想起了這個問題,就根據自己的知識水平,重新推導這個過程。

首先用 IDEA 打開生成的 class 文件。

f9382285e5d4a3bb1cf14c711f6f74b3.png

很直觀的告訴我們結果為 1 ,但這段代碼只解釋了 result,而沒有解釋 why ,繼續用 javap -c 這個命令,結果如圖。

81b73f4097f76d7a2a9fbfc0f45e5ddc.png

以第一次遇見這道題的水准,勉強能看懂第一步的 Java 代碼,第二步的指令就徹底看不懂了。而現在我可以從這些指令里面分析結果了(這里需要分析的就前五行命令,后面指令為打印輸出)。

iconst_1

將常量 1 壓入操作數棧。這個操作是 int 值為 1~5 的時候。如果是 -128~127 這個范圍是用的 bipush x (x 為實際數值)。 -2^15~2^15-1 這個范圍是使用的 sipush x 這個命令(同上)。 -2^31~2^31-1 這個范圍是使用的 ldc 這個命令。

istore_1

彈出操作數棧頂的數(此時為 1)並賦值給局部變量第一個元素即索引為 1 的 a。局部變量是采用的數組形式,索引為 0 的是 main() 的參數 args 。

iload_1

把局部變量索引為 1 的變量(這里是 a)壓入操作數棧,此時棧頂元素為 1 。

incc 1,1(關鍵)

把局部變量索引為 1 的數加 1 ,此時 a 的值為 2。注意:這個結果沒有壓入操作數棧。

istore_1

彈出棧頂的元素(此時為 1)賦值給 a ,覆蓋 a 為 2 的結果。

整個過程大致就是這樣,來一幅圖解釋吧。

11828acf0b8a95654babd8e19e18ccca.png

93fd2f476d4644c93130be723a6d2b66.png

這個問題解決了,那么下面這段代碼就好理解了。

int a = 1;

a = ++a;

System.out.println(a);

直接上截圖吧

6b63053e02fe5649639257858b238495.png

仔細對比一下,你會發現,兩段代碼的指令一模一樣,但執行順序有一點點區別, iinc 和 iload_1 這兩個命令的執行順序變化了一下位置。你還記得這兩條指令的含義嗎?你還記得文章最開始說的區別嗎?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值