深化Java基礎之——數組與內存控制

作爲一個程序猿,大家對數組一定不陌生。平時使用的也比較多,但是往往越簡單的東西,可能越會容易忽略一些細節。

下面是對數組相關知識的一個學習總結,如有不對的地方,歡迎來指正。

數組的初始化

 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程序中使用數組,應多從內存控制的角度來把握程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章