下面是對數組相關知識的一個學習總結,如有不對的地方,歡迎來指正。
數組的初始化
1、Java數組是靜態的
Java數組是靜態的,只有在初始化過後才能使用,而Java數組一旦進行初始化之後,其長度就固定了,不可再改變。
Java數組的初始化有兩種方式:
靜態初始化:由程序員在定義數組時,顯示的指定每個元素的值,數組長度由系統決定
動態初始化:程序員直接指定數組的長度,由系統爲數組元素分配初始值
動態初始化,系統分配元素初始值規則:
基本類型中的整數類型(byte, int, short, long):初始化爲0;
基本類型中的浮點類型(float, double):初始化爲0.0;
基本類型中的字符類型(char):初始化爲'\u0000';
基本類型中的布爾類型(boolean):初始化爲false;
引用類型(類、接口、數組):初始化爲null;
//第一種靜態初始化方式,長度爲2 String[] str = new String{"java基礎","數組初始化"};
//第二種靜態初始化方式,長度爲3 String[] str2 = {"靜態","內存結構","java"};
//動態初始化方式,長度爲4 String[] str3 = new String[4];
//Java語言允許通過length方法獲取數組的長度
System.out.println("str數組長度爲:" + str.length);
System.out.println("str2數組長度爲:" + str2.length);
System.out.println("str3數組長度爲:" + str3.length);
數組變量只是一個引用類型的變量,不是數組本身,而是指向堆內存中的數組對象,通過下面這個圖更清楚的瞭解一下數組的內存分配
上述的三個數組初始化完成之後,長度就被分別固定爲2,3,4,不可改變。但是這裏會有一個數組變量引用的改變,造成數組長度可改變的假象。
str = str2; str3 = str2; System.out.println("str數組長度爲:" + str.length); System.out.println("str3數組長度爲:" + str3.length); //改變str3中的一個元素值 str3[1] = "JVM"; System.out.println(str2[1]);
上述代碼的執行結果爲:str數組長度爲:3
str3數組長度爲:3
JVM
看起來好像是str和str3數組的長度都被改變了,那麼內存中真正發生了什麼事情呢?請看下面的圖:
當執行完前面兩行數組變量賦值後,str,str3數組引用變量都指向了原來的str2數組,堆內存中的其他兩個數組對象會被當做垃圾對象回收掉。
所以對三個數組變量的操作,實際上都是操作的同一個數組對象(這裏有點類似於C/C++中的指針),所以數組中第二個元素也被替換成"JVM"。
這裏就產生了數組初始化後長度發生改變的假象,實際上是指向了其他數組對象,原來數組對象長度並沒有改變。
2.數組一定要初始化嗎?
通過上面的例子,大家應該明白了數組在內存中的分配機制,那麼對於這個問題也就好理解了。
對於數組變量和數組對象這裏一定要區分清楚,數組變量通常是存儲在棧內存的,類似於C語言中的指針,真正意義上的數組初始化,就是在堆中爲數組對象分配內存空間,初始化之後就變成了一個有效的數組對象,只要一個數組變量指向這個有效數組對象,程序中便可使用該數組。通過如下代碼來理解一下:
1 public static void main(String[] args){ 2 //靜態初始化一個int類型數組 3 int[] nums = new int{1, 2, 3, 4}; 4 //定義一個int類型的數組變量,不初始化 5 int[] temp; 6 //輸出nums數組中一個元素 7 System.out.println("nums數組第二個元素爲:" + nums[1]); 8 //讓temp數組變量指向nums所引用的數組對象 9 temp = nums; 10 //更改temp數組的第二個值,這裏已經可以使用temp數組 11 temp[1] = 5; 12 //nums數組的第二個元素值爲5 13 System.out.println("nums數組第二個元素爲:" + nums[1]); 14 }
代碼第5行並沒有對temp進行初始化,而是在第9行,讓其指向了一個有效的數組對象,這時nums和temp兩個變量指向的是同一塊內存,這樣便可以使用temp數組。
關於引用數組的初始化在下面的沒有多維數組中順便總結。
使用數組
沒有多維數組
Java允許將多維數組當做一維數組處理。對於int[][] nums 類型的數組,就是元素類型爲int[] 的一維數組,nums數組的每個int[] 型元素再指向內存中其他的int型數據。
對於nums可以只初始化最左邊的維數,nums = new int[4][],這些元素還要進一步初始化,讓這4個int[] 型元素分別指向4個有效的數組對象,看如下例子。
1 int[][] a = new int[4][]; 2 //4個引用類型元素,所以會輸出4個null 3 System.out.println(Arrays.toString(a)); 4 //初始化a數組前兩個元素 5 a[0] = new int[]{1, 2}; 6 a[1] = new int[]{3, 4, 5}; 7 //輸出a數組第二個元素指向的內存空間的第3個元素 8 System.out.println(a[1][2]);
註釋其實寫的比較清楚了,爲了更深刻的理解,結合代碼來看下面的內存分配圖:
因爲是a數組元素是引用類型,所以系統初始化爲null,前兩個元素在5、6行又分別初始化,所以指向了其他的內存空間。
通過上面的分析可以看出,多維數組的本質依然是一維數組,當然一維數組的元素也可以是二維數組,這樣就是三維數組,以此類推。
在Java程序中使用數組,應多從內存控制的角度來把握程序。