java?數(shù)組越界判斷和獲取數(shù)組長度的實現(xiàn)方式
1. 背景介紹
java中的數(shù)組比c語言中的數(shù)組,多了兩個很重要的功能
- 當(dāng)索引越界時, 會自動拋出ArrayIndexOutOfBoundsException, 避免一錯再錯
- 另一個很重要的方法是獲取數(shù)組長度
這兩個功能都不是通過java代碼層面實現(xiàn)的, 而是在jvm中通過c++來實現(xiàn)的. 本文就針對這連個點來一探究竟
2. 原始java代碼
public class TestArrayIndexOutOfBoundsException { public static void main(String[] args) { int[] is = new int[2]; int x = is[5]; System.out.println(x); int len = is.length; System.out.println(len); } }
3. java代碼對應(yīng)的反編譯字節(jié)碼
0 iconst_2 1 newarray 10 (int) // 創(chuàng)建長度為2的int型數(shù)組 3 astore_1 // 將數(shù)組is存儲到local stack的slot1中 4 aload_1 // 將數(shù)組is壓入操作數(shù)棧 5 iconst_5 // 將常量5壓入操作數(shù)棧 6 iaload // 這個指令就是通過數(shù)組索引獲取元素, is[5] 7 istore_2 8 getstatic #2 <java/lang/System.out> 11 iload_2 12 invokevirtual #3 <java/io/PrintStream.println> 15 aload_1 // 將數(shù)組is壓入操作數(shù)棧 16 arraylength // 獲取is數(shù)組的長度 17 istore_3 18 getstatic #2 <java/lang/System.out> 21 iload_3 22 invokevirtual #3 <java/io/PrintStream.println> 25 return
4. jvm實現(xiàn)分析
4.1 獲取數(shù)組長度arraylength指令核心代碼分析
// hotspot\src\share\vm\interpreter\bytecodeInterpreter.cpp void BytecodeInterpreter::run(interpreterState istate) { // 省略無關(guān)代碼 CASE(_arraylength): { // java中的對象實例, 對應(yīng)的c++實例就是arrayOopDesc arrayOop ary = (arrayOop) STACK_OBJECT(-1); CHECK_NULL(ary); SET_STACK_INT(ary->length(), -1); // 就是通過ary->length()這個方法來獲取數(shù)組長度 UPDATE_PC_AND_CONTINUE(1); } } // 省略無關(guān)代碼
4.2 獲取數(shù)組元素iaload指令分析
// hotspot\src\share\vm\interpreter\bytecodeInterpreter.cpp void BytecodeInterpreter::run(interpreterState istate) { // 省略無關(guān)代碼 #define ARRAY_INTRO(arrayOff) \ arrayOop arrObj = (arrayOop)STACK_OBJECT(arrayOff); \ // 從局部變量表中獲取數(shù)組對象is jint index = STACK_INT(arrayOff + 1); \ // 從局部變量表中獲取索引5 char message[jintAsStringSize]; \ CHECK_NULL(arrObj); \ if ((uint32_t)index >= (uint32_t)arrObj->length()) { \ // 判斷索引是否大于或等于數(shù)組長度 sprintf(message, "%d", index); \ VM_JAVA_ERROR(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), \ // 如果越界, 則拋出ArrayIndexOutOfBoundsException異常 message); \ } // 省略無關(guān)代碼 #define ARRAY_LOADTO32(T, T2, format, stackRes, extra) \ { \ ARRAY_INTRO(-2); \ // 獲取數(shù)組所在的地址 (void)extra; \ SET_ ## stackRes(*(T2 *)(((address) arrObj->base(T)) + index * sizeof(T2)), \ // 根據(jù)數(shù)組所在地址,加上索引計算的偏移地址, 獲得數(shù)組指定元素 -2); \ UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); \ } // 省略無關(guān)代碼 CASE(_iaload): // 此處對應(yīng)的就是iaload指令的具體實現(xiàn) ARRAY_LOADTO32(T_INT, jint, "%d", STACK_INT, 0); } // 省略無關(guān)代碼
通過上面代碼的分析, 可以jvm是通過(uint32_t)index >= (uint32_t)arrObj->length()來判斷數(shù)組越界
5. 小結(jié)一下
java中的數(shù)組和c語言數(shù)組差異很大, c語言中的數(shù)組更原始,直接和內(nèi)存對應(yīng)。而java中的數(shù)組類型其實是經(jīng)過了arrayOopDesc的封裝,因而能獲得更豐富的信息,做更多語言層面的檢查。
java 數(shù)組越界問題
Java中數(shù)組初始化和OC其實是一樣的,分為動態(tài)初始化和靜態(tài)初始化,
- 動態(tài)初始化:指定長度,由系統(tǒng)給出初始化值
- 靜態(tài)初始化:給出初始化值,由系統(tǒng)給出長度
在我們使用數(shù)組時最容易出現(xiàn)的就是數(shù)組越界問題,好了,下面來演示一下
int [][] array = {{1,2,3},{1,4}}; System.out.println(array[1][2]);
這是一個二維數(shù)組,很明顯,數(shù)組越界了,控制臺中會打印如下信息:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at demo.Array.main(Array.java:31)
很準(zhǔn)確的定位到31行
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于SpringBoot+Avue實現(xiàn)短信通知功能
Avue是基于vue和element-ui的快速開發(fā)框架 ,它的核心是數(shù)據(jù)驅(qū)動UI的思想,讓我們從繁瑣的crud開發(fā)中解脫出來,本文將給大家介紹一下使用SpringBoot+Avue實現(xiàn)短信通知功能,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-09-09Java實現(xiàn)調(diào)用對方http接口得到返回數(shù)據(jù)
這篇文章主要介紹了Java實現(xiàn)調(diào)用對方http接口得到返回數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09詳解SpringBoot Redis自適應(yīng)配置(Cluster Standalone Sentinel)
這篇文章主要介紹了詳解SpringBoot Redis自適應(yīng)配置(Cluster Standalone Sentinel),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java動態(tài)獲取實現(xiàn)某個接口下所有的實現(xiàn)類對象集合
今天小編就為大家分享一篇關(guān)于Java動態(tài)獲取實現(xiàn)某個接口下所有的實現(xiàn)類對象集合,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12Java異常--常見方法--自定義異常--增強try(try-with-resources)詳解
這篇文章主要介紹了Java異常--常見方法--自定義異常--增強try(try-with-resources)的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03