Java記憶體區域分為五個部分
Heap(堆):用於存放所有的物件實例和陣列。堆是所有執行緒共享的記憶體區域,並且是Java記憶體管理(垃圾回收)的主要區域。Stack(堆棧):每個執行緒都有一個專屬的Java堆棧,用於存儲局部變量、方法參數和執行緒的調用狀態。當方法執行時會自動創建相應的堆棧幀並進行管理。Method Area(方法區):也稱為非堆區或永久代(在Java8之前)。存放類別的結構信息、靜態變數、常量池(常量字串、數字)、方法代碼等。Java8之後引入了元數據區(Metaspace)替代了永久代。Program counter register(程式計數器):每個執行緒都有自己的程序計數器,用於記錄當前執行的Java字節碼指令的地址。如果是本地方法(native method),這個計數器則會保持未定義狀態。Native Method Stack(本地方法棧):支援本地方法執行(通常是C或C++程式碼),與Java堆棧相似,但專門用來處理執行本地方法時所需的數據。(以上內容取自ChatGPT,如有錯誤請包涵)
會特別講一下記憶體相關的原因在於Array有一部分會跟記憶體有所關聯,所以特別提了一些。
Heap 和Stack跟Array相關的有Heap和Stack,舉例宣告一個int[] arr = new int[]{1,2,3};。
Heap :存放array的元素:1, 2, 3。stack :存放array聲明的局部變量:arr。還記得前幾天在terminal 中印出Hello World 的程式碼嗎?
class HelloWorld {
public static void main(String[] args){
long num1 = 20L;
int num2 = (int) num1;
System.out.println(num2);
}
}
HelloWorld:類(class) 是Java中的核心概念。main():程式的入口點。num1:局部變量。num2:局部變量。if、for所宣告的變量。Array in the 記憶體先來看陣列在記憶體存放的方式:
int[] arr = new int[]{1,2,3};
int[] arr1 = new int[5];
先來張圖片

靜態宣告了一個新的array 時,會在stack 中放入宣告的變數名稱arr 。heap 中找了一個位置將所宣告的值(上面的範例是1,2,3)放入,並得到一個16進制的位址(I@16b98e56),stack中的arr 紀錄的也是這個16進制的位址。index 會從0開始也是由於計算的偏移量從0開始較好計算。動態宣告了一個新的array 時,會在stack 中放入宣告的變數名稱arr 。heap 中找了一個位置將所宣告的長度(上面的範例是5)放入,並得到一個16進制的位址(I@16b12f91),stack中的arr 紀錄的也是這個16進制的位址。動態宣告array時,所有的值都會先賦值為初始值。array了你的array(array in array)二維array,可以把它看成是嵌套的的感覺,但是在記憶體中是沒有二維的概念,指向的依舊是記憶體位址 (16進制的位址)。
宣告的方式
// 靜態宣告
int[][] arr = new int[][] {{1,2,3},{4,5},{6,7,8,9}};
// 動態宣告:這樣宣告時,每一個元素內的長度都固定為5
int[][] arr1 = new int[3][5];
// 動態宣告:這樣宣告時,可以動態設定每一個元素內的長度
String[][] arr2 = new String[5][];
arr2[1] = new String[2];
arr2[1][0] = "helloooooo";
arr2[2] = new String[]{"abc","def","ghi"};
調用
int[][] arr = new int[][] {{1,2,3},{4,5},{6,7,8,9}};
System.out.println(arr[0]); // [I@16b98e56,這是存放在記憶體中arr第一個元素的位址
System.out.println(arr[0][1]); // 2
String[][] arr2 = new String[5][];
System.out.println(arr2[0]); // null,因為未將第一層的陣列給定長度,記憶體中無法得知應該提供多少長度存放,所以不會事先保留空間
System.out.println(arr2[0][0]); // 會報錯,因為第一層已經是null了,表示並沒有這個地方
來個圖片



要小心不可以直接使用=進行,因為只是指向相同記憶體的位置,改動時會兩個都一起更改。
int[] arr = new int[]{1,2,3};
int[] arr1 = new int[arr.length];
for(int i = 0; i < arr.length; i++) {
arr1[i] = arr[i];
};
這樣才可以完全複製
Java SE API 中也有寫好可以使用的Arrays類 可以使用,位置在java.util.Arrays
異常:
ArrayIndxOutOfBoundsException:邊界錯誤,當一個array長度為5時,卻調用了第6個元素,會出現邊界錯誤。
int[] arr = new arr[5];
System.out.println(arr[5]); //ArrayIndxOutOfBoundsException
還記得調用array時是從0開始嗎?所以arr第五個元素是length - 1,會是4
NullPointerException:空指標例外或空指針異常,當二維array(方便稱呼)的元素未給定長度時,調用會出現空指針異常的錯誤,因為第二層未給定長度,所以第一層只會紀錄為null,所以它並沒有再指向記憶體中的任何位址。
int[][] arr = new arr[5][];
System.out.println(arr[0][2]); //NullPointerException