最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中i++的一些問題總結(jié)

 更新時間:2020年12月06日 09:13:28   作者:小小小小小樂  
這篇文章主要給大家介紹了關(guān)于Java中i++的一些問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

參考內(nèi)容:

  • 深入理解Java虛擬機(jī)(JVM高級特性與最佳實踐) ——周志明老師
  • 尚硅谷深入理解JVM教學(xué)視頻——宋紅康老師

在本文展開前,讀者需要了解一些字節(jié)碼有關(guān)的知識,以及JVM虛擬機(jī)棧中棧幀的局部變量表和操作數(shù)棧等知識,筆者在這里只給出一些大概的簡述。

字節(jié)碼

  • Java字節(jié)碼對于虛擬機(jī),就好像匯編語言對于計算機(jī),屬于基本執(zhí)行指令。
  • 虛擬機(jī)的指令由一個字節(jié)長度的、代表著某種特定操作含義的數(shù)字(稱為操作碼,Opcode)以及跟隨其后的零至多個代表此操作所需參數(shù)(稱為操作數(shù),Operands)而構(gòu)成。由于Java虛擬機(jī)采用面向操作數(shù)棧而不是寄存器的結(jié)構(gòu),所以大多數(shù)的指令都不包含操作數(shù),只有一個操作碼。

局部變量表

局部變量表:Local Variables,被稱之為局部變量數(shù)組或本地變量表

定義為一個數(shù)字?jǐn)?shù)組,主要用于存儲方法參數(shù)和定義在方法體內(nèi)的局部變量,這些數(shù)據(jù)類型包括各類基本數(shù)據(jù)類型、對象引用(reference),以及returnAddress類型。

由于局部變量表是建立在線程的棧上,是線程的私有數(shù)據(jù),因此不存在數(shù)據(jù)安全問題。

局部變量表所需的容量大小是在編譯期確定下來的,并保存在方法的Code屬性的maximum local variables數(shù)據(jù)項中。在方法運(yùn)行期間是不會改變局部變量表的大小的。

操作數(shù)棧

操作數(shù)棧:Operand Stack ,使用數(shù)組實現(xiàn)的。

每一個獨立的棧幀除了包含局部變量表以外,還包含一個后進(jìn)先出(Last - In - First -Out)的 操作數(shù)棧,也可以稱之為 表達(dá)式棧(Expression Stack)

操作數(shù)棧,在方法執(zhí)行過程中,根據(jù)字節(jié)碼指令,往棧中寫入數(shù)據(jù)或提取數(shù)據(jù),即入棧(push)和 出棧(pop)

  • 某些字節(jié)碼指令將值壓入操作數(shù)棧,其余的字節(jié)碼指令將操作數(shù)取出棧。使用它們后再把結(jié)果壓入棧
  • 比如:執(zhí)行復(fù)制、交換、求和等操作
  • 操作數(shù)棧,主要用于保存計算過程的中間結(jié)果,同時作為計算過程中變量臨時的存儲空間。

接下來就是本文的正式內(nèi)容,首先,我們先給出兩個結(jié)論:

  • i++與++i在不同情況下可能會有不同的結(jié)論;
  • 實例變量/類變量的i++并不是一個原子性的操作。

首先我們看一下i++與++i的解析:

當(dāng)i++或者++i沒有涉及到其他操作時,兩者是沒有區(qū)別的。

// i++
public void method1(){
 int i = 10;
 i++;
}
// ++i
public void method2(){
 int i = 10;
 ++i;
}

對應(yīng)的字節(jié)碼指令操作為:

// method1
0 bipush 10 // 將10這個整數(shù)壓入操作數(shù)棧
2 istore_1	// 將操作數(shù)棧棧頂元素保存到局部變量表中索引為1處
3 iinc 1 by 1 // 局部變量表中索引為1處的元素,也就是i進(jìn)行自增(這一步是在局部變量表上直接進(jìn)行的,與操作數(shù)棧無關(guān))
6 return // 方法返回

// method2
0 bipush 10
2 istore_1
3 iinc 1 by 1 // ++i
6 return

其中關(guān)于給出的具體字節(jié)碼細(xì)節(jié)以及棧幀中操作數(shù)棧、局部變量表在本文開頭給出了一些簡介,具體內(nèi)容不展開描述,讀者可翻閱與之有關(guān)的資料。

通過反編譯可以看出,i++與++i的字節(jié)碼在沒有和其他操作組合時,字節(jié)碼是完全相同的。

當(dāng)i++或者++i涉及到其他操作時,兩者的字節(jié)碼會有一些改變。

public void method7(){
  int i = 10;
  int a = i++;

  int j = 20;
  int b = ++j;
 }

對應(yīng)的的字節(jié)碼指令:

 0 bipush 10
 2 istore_1	
 3 iload_1		// i++先從局部變量表中讀取i到操作數(shù)棧
 4 iinc 1 by 1	// i直接在局部變量表上進(jìn)行自增
 7 istore_2		// 將操作數(shù)棧上讀取到的i的值賦值給a,也就是10
 8 bipush 20
10 istore_3
11 iinc 3 by 1	// ++j則先在局部變量表上進(jìn)行自增
14 iload_3		// 再從局部變量表中讀取j到操作數(shù)棧
15 istore 4		// 將操作數(shù)棧上讀取到的j的值賦值給b,也就是21
17 returns

通過反編譯可以看出,i++與++i的字節(jié)碼在沒有和其他操作組合時,i++是先取值再自增,而++i是先自增再取值。

還有一個關(guān)于i=i++的解析:

public void method8(){
  int i = 10;
  i = i++;
  System.out.println(i);//10
 }

對應(yīng)的字節(jié)碼指令:

 0 bipush 10
 2 istore_1
 3 iload_1		// 從局部變量表中讀取i到操作數(shù)棧
 4 iinc 1 by 1	// i直接在局部變量表上進(jìn)行自增,此時i = 11
 7 istore_1		// 將之前操作數(shù)棧上讀取到的i的值賦值給i,之前自增的值被覆蓋了,i = 10
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #5 <java/io/PrintStream.println>
15 return

然后看一下實例變量i++這行代碼的對應(yīng)的字節(jié)碼

首先我們定義一個類

/**
 * @author XiaoLe
 * @create 2020-12-04 21:15
 * @description
 */
public class Test {
 private int i = 0;
 public void test(){
  i++;
 }
}

通過反編譯查看test方法中的字節(jié)碼:

 0 aload_0	
 1 dup
 2 getfield #2 <day001/Test.i> // 獲取到Test的i變量的值
 5 iconst_1	// 將int類型常量1壓入棧
 6 iadd	// 棧頂兩個元素相加后返回值入棧
 7 putfield #2 <day001/Test.i>
10 return

可以看到,i++這行代碼被拆分為三個字節(jié)碼,所以在一些并發(fā)情況下,i++如果不做同步處理,就可能會出現(xiàn)數(shù)據(jù)非一致性。

到此這篇關(guān)于Java中i++的一些問題總結(jié)的文章就介紹到這了,更多相關(guān)Java中i++問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?Stream實現(xiàn)多字段分組groupingBy操作詳解

    Java?Stream實現(xiàn)多字段分組groupingBy操作詳解

    Stream是Java8的一個新特性,主要用戶集合數(shù)據(jù)的處理,如排序、過濾、去重等等功能,本文就來講講如何利用Stream實現(xiàn)比較優(yōu)雅的按多字段進(jìn)行分組groupingBy吧
    2023-06-06
  • java實現(xiàn)讀取帶合并單元格的Excel

    java實現(xiàn)讀取帶合并單元格的Excel

    這篇文章主要為大家詳細(xì)介紹了java如何實現(xiàn)讀取帶合并單元格的Excel,文中的示例代碼講解詳細(xì), 感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • Spring Boot使用模板引擎JSP實例解析

    Spring Boot使用模板引擎JSP實例解析

    這篇文章主要介紹了Spring Boot使用模板引擎JSP實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Java的Semaphore信號量使用及原理解讀

    Java的Semaphore信號量使用及原理解讀

    這篇文章主要介紹了Java的Semaphore信號量使用及原理解讀,Semaphore(信號量)是Java中一個并發(fā)控制工具,用于控制對共享資源的訪問,它基于計數(shù)器的原理,可以限制同時訪問某個資源的線程數(shù)量,需要的朋友可以參考下
    2023-12-12
  • Maven工程pom中如何定義jdk版本

    Maven工程pom中如何定義jdk版本

    這篇文章主要介紹了Maven工程pom中如何定義jdk版本,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java多線程死鎖與資源限制操作

    Java多線程死鎖與資源限制操作

    這篇文章主要介紹了Java多線程死鎖與資源限制操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java控制臺輸入scanner的方法及代碼詳解

    Java控制臺輸入scanner的方法及代碼詳解

    在本篇內(nèi)容里小編給大家分享的是一篇關(guān)于Java控制臺輸入scanner的方法及實例代碼,有需要的朋友們可以參考下。
    2022-11-11
  • springboot封裝響應(yīng)實體的實例代碼

    springboot封裝響應(yīng)實體的實例代碼

    這篇文章主要介紹了springboot封裝響應(yīng)實體,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • java程序中protobuf的基本用法示例

    java程序中protobuf的基本用法示例

    這篇文章主要給大家介紹了關(guān)于java程序中protobuf的基本用法,protobuf 與json相比具有 壓縮比高 、解壓縮速度更快的優(yōu)點,本文通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Java for-each循環(huán)使用難題2例(高級使用方法)

    Java for-each循環(huán)使用難題2例(高級使用方法)

    從Java5起,在Java中有了for-each循環(huán),可以用來循環(huán)遍歷collection和array。For each循環(huán)允許你在無需保持傳統(tǒng)for循環(huán)中的索引,或在使用iterator /ListIterator時無需調(diào)用while循環(huán)中的hasNext()方法就能遍歷collection
    2014-04-04

最新評論

仙桃市| 鹤庆县| 大冶市| 讷河市| 双鸭山市| 琼海市| 天全县| 阆中市| 隆回县| 洞口县| 敦化市| 南城县| 左云县| 民丰县| 信阳市| 枣庄市| 尖扎县| 东山县| 新源县| 常德市| 紫阳县| 纳雍县| 茌平县| 梅河口市| 广汉市| 澜沧| 邵阳县| 乌苏市| 宝坻区| 佳木斯市| 方城县| 乐至县| 堆龙德庆县| 深州市| 奉新县| 黄冈市| 托克逊县| 逊克县| 克什克腾旗| 杂多县| 兰州市|