從位元組碼角度分析 i++ 和 ++i 實現
最近看到個面試題:
int j=0;
for(int i=0;i<100;i++)
j = j++;
System.out.println(j);
輸出結果是0,如果換成j++,那麼輸出100,這是為什麼?
對於這種問題,其實有點經驗的程式設計師都知道,前置++和後置++的運算區別:
1、前置++是將自身加1的值賦值給新變數,同時自身也加1
2、後置++是將自身的值賦給新變數,然後才自身加1
話雖這麼說,那怎麼來證明上面兩點呢?
萬物皆有始有終,對於程式碼,只能從位元組碼的角度看看是不是能挖掘有價值的資訊。
在講位元組碼之前,先簡單的瞭解下Java棧,在JVM中有這麼一個數據結構叫Java棧,當執行緒啟動的時候,會分配一塊記憶體當做該執行緒的棧,每個棧由一系列的棧幀組成。每個棧幀對應一個方法,當執行緒執行方法時,就是棧幀出棧入棧的過程。
每個棧幀包含三部分資料:本地變數(引數+方法內的變數)、運算元棧和其它資料,本文主要涉及本地變數和運算元棧。
先看看後置++的實現:
public static void main(String[] args){
int i= 0;
i = i++;
}
編譯之後的位元組碼如下:
iconst_0 //把數值0 push到運算元棧
istore_1 // 把運算元棧寫回到本地變數第2個位置
iload_1 // 把本地變數第2個位置的值push到運算元棧
iinc 1,1 // 把本地變量表第2個位置加1
istore_1 // 把操作資料棧寫回本地變數第2個位置
整個過程這樣的:
可以發現變數a在執行iinc 1,1的時候已經變成1了,但是istore_1又把變數a所在位置覆蓋成了0,所以執行完i = i++,i還是原來那個值。
另外,來看下前置++的實現:
位元組碼就不再解釋了,整個過程實現如下:
和後置++不同的地方在於,在變數進入運算元棧之前,就先執行了iinc指令,所以進入運算元的值是加1後的值,最後寫回的值也是最新值。
轉載自狼哥的部落格 https://www.jianshu.com/p/7988e646a37e
相關推薦
從位元組碼角度分析 i++ 和 ++i 實現
最近看到個面試題: int j=0; for(int i=0;i<100;i++) j = j++; System.out.println(j); 輸出結果是0,如果換成j++,那麼輸出100,這是為什麼? 對於這種問題,其實有點經驗的程式設
從位元組碼角度分析java泛型陣列的問題
關於java的泛型陣列這個問題,之前就有遇到過,不過當時以為是自己程式碼語法錯誤的問題,現在系統地對java的基礎知識進行深入總結,才發現這個問題某種程度是和泛型的型別擦除機制有關,其實我覺得這個解釋有它的道路但是還是比較勉強。下面我們從位元組碼角度試圖去分析一下java某
Java 函式呼叫是傳值還是傳引用? 從位元組碼角度來看看!
本文是網友KailunTalk文章的精簡版, 他從位元組碼的角度解釋了Java 函式呼叫中傳遞引數的方式, 充分體現了一個程式設計師深度挖掘,瞭解底層的精神, 原文地址:https://my.oschina.net/kailuncen/blog/915043 1傳值還是
從源碼角度分析 Kotlin by lazy 的實現
other aar turned 周期 基本類 any 是的 如果 最新 by lazy 的作用 延遲屬性(lazy properties) 是 Kotlin 標準庫中的標準委托之一,可以通過 by lazy 來實現。 其中,lazy() 是一個函數,可
Android進階:二、從源碼角度看透 HandlerThread 和 IntentService
pri vat thread err 應該 red service adp 結束 上篇文章我們講日誌的存儲策略的時候用到了HandlerThread,它適合處理“多而小的任務”的耗時任務的時候,避免產生太多線程影響性能,那這個HandlerThread的原理到底是怎樣的呢?
從volatile分析i++和++i非原子性問題
目錄 1、可見性(Visibility) 2、原子性(Atomicity) 3、Java記憶體模型的抽象結構( JMM ) 4、volatile 5、 多執行緒下的i++問題 5、自定義實現i++原子操作 5.1
Java i++ 和 ++i 的字節碼分析
陌生 位置 clas ava .class 發現 .html length ref 一、描述 想必大家對i++;++i的問題一定不會陌生;例如: int j=0; for(int i=0;i<100;i++) { j=j++; } System.out.print
從實例角度分析java的public、protected、private和default訪問權限
png mage 分享 import 調用 ring lin tro 1.5 一、public 同一個package 1.本類內部 public class A { public int f=1; public void m1() {}
易經之乾卦和坤卦(從職場角度分析)
驚歎中國文化的博大精深,想不到易經中隱藏著這麼大的世界。開始覺得古人的智慧在現代社會體系中已過時,但講師從職場角度的一番講解。讓我驚歎古人的智慧,甚至讓我感到恐怖,簡單的幾句話便濃縮了整個人生。這背後到底有多大的智慧和人生閱歷。原來"聖人"是真的存在的。 乾卦:主要針對自己做大事者。類似三國
java的++i和i++的分析
關於自增自減,先來一道題,大家嘗試著做一下: 1 public static void main(String[] args) { 2 3 int a=2; 4 int b=a++; 5 int c=--a; 6
從字節碼角度分析重載與重寫
字節 常量池 開始 .text 方法區 stat special 以及 ora 目錄 從字節碼角度分析重載與重寫 代碼分析 字節碼分析 驗證
JavaScript運算符:遞增和遞減(++i,--i 和 i++,i-- 的區別)
nbsp key mic comment 包含 -- 效應 1+n com 遞增和遞減操作符直接借鑒自C,而且各有兩個版本:前置型 (遞增 ++i ,遞減 --i )和 後置型 (遞增 i++ ,遞減 i-- )。書本上對兩者的定義是:前置型應該位於要操作的變量之前,而後置
【原創】源碼角度分析Android的消息機制系列(一)——Android消息機制概述
run 權限 開發 等待 通過 讀取 概述 走了 color ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 1.為什麽需要Android的消息機制 因為Android系統不允許在子線程中去訪問UI,即Android系統不允許在子線程中更新UI。 為什麽不允許
【原創】源碼角度分析Android的消息機制系列(二)——ThreadLocal的工作過程
機制 simple hand 這就是 數據存儲 read etc lena 並且 ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 在上一篇文章中,我們已經提到了ThreadLocal,它並非線程,而是在線程中存儲數據用的。數據存儲以後,只能在指定的線程中獲取到數據
【原創】源碼角度分析Android的消息機制系列(三)——ThreadLocal的工作原理
沒有 cit gen 管理 pre 靜態 bsp 允許 clas ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 先看Android源碼(API24)中對ThreadLocal的定義: public class ThreadLocal<T>
【原創】源碼角度分析Android的消息機制系列(四)——MessageQueue的工作原理
enc 容易 工作 trie oss 當前 within which ptime ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 MessageQueue,主要包含2個操作:插入和讀取。讀取操作會伴隨著刪除操作,插入和讀取對應的方法分別為enqueueMes
【原創】源碼角度分析Android的消息機制系列(六)——Handler的工作原理
urn long empty isa pat stat 開啟 it is performed ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 先看Handler的定義: /** * A Handler allows you to send and proc
Android的Message Pool是個什麽鬼,Message Pool會否引起OOM——源代碼角度分析
頭部 mar mark 判斷 線程池 ets set ret 元素 引言 Android中,我們在線程之間通信傳遞通常採用Android的消息機制,而這機制傳遞的正是Message。 通常。我們使用Message.obtain()和Handler.o
js ++i和i++的區別
bsp ons http pre sans 前綴 -h 單位 alt ++i和i++的定義: 1. 如果用前綴運算符對一個變量增1(減1),則在將該變量增1(減1)後,用新值在表達式中進行其他的運算。 2. 如果用後綴運算符對一個變量增1(減1),則用該變量的
i++和++i 的區別
++i ++ 輸出結果 print body nbsp pos 之前 ont 1. i++為後自增 整體表達式的值為自增之前的值 2. ++i為前自增 整體表達式的值為自增後的值 # include <stdio.h> int main(void)