Java到底有沒有多維陣列?

2020-07-16 10:05:11
Java 中沒有多維陣列的概念,從陣列底層的執行機制上來看 Java 沒有多維陣列,但是 Java 提供了支援多維陣列的語法,可以實現多維陣列的功能。

Java 語言裡的陣列型別是參照型別,因此陣列變數其實是一個參照,這個參照指向真實的陣列記憶體。陣列元素的型別也可以是參照,如果陣列元素的參照再次指向真實的陣列記憶體,這種情形看上去很像多維陣列。

定義陣列型別的語法type[] arrName;是典型的一維陣列的定義語法,其中 type 是陣列元素的型別。如果希望陣列元素也是一個參照,而且是指向 int 陣列的參照,則可以把 type 具體成 int[](前面已經指出,int[] 就是一種型別,int[] 型別的用法與普通型別並無任何區別),那麼上面定義陣列的語法就是int[][] arrName

如果把 int 這個型別擴大到 Java 的所有型別(不包括陣列型別),則出現了定義二維陣列的語法:

type[][] arrName;

Java 語言採用上面的語法格式來定義二維陣列,但它的實質還是一維陣列,只是其陣列元素也是參照,陣列元素裡儲存的參照指向一維陣列。

接著對這個“二維陣列”執行初始化,同樣可以把這個陣列當成一維陣列來初始化,把這個“二維陣列”當成一個一維陣列,其元素的型別是 type[] 型別,則可以採用如下語法進行初始化:

arrName = new type[length][]

上面的初始化語法相當於初始化了一個一維陣列,這一維陣列的長度是 length。同樣,因為這個一維陣列的陣列元素是參照型別(陣列型別)的,所以系統為每個陣列元素都分配初始值:null。

這個二維陣列實際上完全可以當成一維陣列使用:使用new type[length]初始化一維陣列後,相當於定義了 length 個 type 型別的變數。類似的,使用new type[length][]初始化這個陣列後,相當於定義了 length 個 type[] 型別的變數。當然,這些 type[] 型別的變數都是陣列型別,因此必須再次初始化這些陣列。

下面程式示範了如何把二維陣列當成一維陣列處理。
public class TwoDimensionTest {
    public static void main(String[] args) {
        // 定義一個二維陣列
        int[][] a;
        // 把a當成一維陣列進行初始化,初始化a是一個長度為4的陣列
        // a陣列的陣列元素又是參照型別
        a = new int[4][];
        // 把a陣列當成一維陣列,遍歷a陣列的每個陣列元素
        for (int i = 0, len = a.length; i < len; i++) {
            System.out.println(a[i]); // 輸出 null null null null
        }
        // 初始化a陣列的第一個元素
        a[0] = new int[2];
        // 存取a陣列的第一個元素所指陣列的第二個元素
        a[0][1] = 6;
        // a陣列的第一個元素是一個一維陣列,遍歷這個一維陣列
        for (int i = 0, len = a[0].length; i < len; i++) {
            System.out.println(a[0][i]); // 輸出 0 6
        }
    }
}
上面程式中粗體字程式碼部分把 a 這個二維陣列當成一維陣列處理,只是每個陣列元素都是 null,所以看到輸出結果都是 null。下面結合示意圖來說明這個程式的執行過程。

程式中程式碼int[][] a;將在棧記憶體中定義一個參照變數,這個變數並未指向任何有效的記憶體空間,此時的堆記憶體中還未為這行程式碼分配任何儲存區。

程式中程式碼a = new int[4][];對 a 陣列執行初始化,這行程式碼讓 a 變數指向一塊長度為 4 的陣列記憶體,這個長度為 4 的陣列裡每個陣列元素都是參照型別(陣列型別),系統為這些陣列元素分配預設的初始值:null。此時 a 陣列在記憶體中的儲存示意圖如圖 1 所示。
將二維數組當成一維數組初始化的存儲示意圖
圖 1  將二維陣列當成一維陣列初始化的儲存示意圖