Java進階---數組與內存控制

Java進階——數組與內存控制

下面將會深入探討Java數組的靜態特徵。使用Java數組前必須對數組進行初始化,初始化的過程即給數組的所有元素都分配合適的內存空間,並指定初始值的過程。數組初始化以後將不能重新改變數組對象在內存中的位置和大小。從用法角度看,數組元素相當於普通變量,程序既可以吧數組的值賦給普通變量,也可以把普通變量的值賦給數組元素。但其實質是對內存中數組元素對象的操作。

1、數組初始化

Java語言是典型的靜態語言,所以Java的數組也是靜態的。Java中的數組必須經初始化後纔可以使用,初始化即爲數組對象的所有元素分配一個連續的內存空間,併爲每個元素指定初始值。數組的初始化有兩種方式:

>靜態初始化:由程序員顯式地指定每個數組元素的初始值,由系統決定數組的長度;

>動態初始化:程序員只指定數組長度,由系統爲數組元素分配初始值。

下面是兩種初始化方式的實例:

public class test01 {

      public static void main(String[] args) {

             //靜態初始化數組

             String[] str0 = new String[]{"小武靈靈" , "41009160"};

             //靜態初始化的簡化形式

             String[] str1 = {"小武靈靈" , "41009160"};

             //動態初始化

             String[] str2 = new String[2];

      }

}

Java語言的數組變量是引用類型的變量,上面的三個數組變量按照聲明的前後順序(注意這裏不是初始化的先後順序)存儲在main棧區中,其引用的數組是按照數組元素的順序分別在堆內存中分配到長度爲2的連續空間。

注意,雖然這裏str0str1變量引用的數組內容相同,但是絕不是同一個數組,也就是說內存中除了str2外,還有兩個長度內容都相同的數組。

注意,鼎泰初始化和動態初始化不能同時使用。

而執行動態初始化時,程序員指定了數組的長度,即爲每個數組元素指定所需的內存空間,系統負責爲這些數組元素分配初始值。系統將按照如下規則分配到初始值:

>基本類型:

      >整數類型(byte , short , int , long):數組元素的初始值爲0

      >浮點類型(float , double)0.0

      >字符類型(char , string)’\u000’

      >布爾型(boolean)false

>引用類型(類、接口和數組)null

1)、數組變量和數組對象

Java的數組變量是一種引用類型的變量,通常情況下被存放在棧內存中,它並不是數組本身,它只是指向堆內存中的數組對象(C語言裏的指針差不多)

數組對象是保存在堆內存中的連續內存空間。

理解了這兩個概念之後,我們可以對數組的初始化有一個更深的認識,即對數組執行初始化,其實並不是對數組變量執行初始化,而是要對數組對象執行初始化(即爲該數組對象分配一塊連續的內存空間)

認識到這一點之後我們可以解釋這樣一種假象,即認爲數組的長度是可變的,例如下面的實例:

public class test01 {

      public static void main(String[] args) {

             String[] str0 = new String[]{"小武靈靈" , "41009160" , "陝西師範大學"};

             String[] str1 = new String[2];

             str1 = str0;

             System.out.println("str1的長度爲:" + str0.length);

      }

}

相信大家可以自行解釋這種假象,這裏我就不解釋啦!

      2)、基本類型數組的初始化

基本類型數組的初始化過程爲:程序直接爲數組分配內存空間,再將數組元素的值存入對應的內存裏。例如下面的代碼塊:

String[] str;

str = new String[]{“小武靈靈” , 41009160, “地信1”};

注意,所有局部變量都是放在棧內存裏保存的,不管其是基本類型的變量,還是引用類型的變量,都是存儲在各自的方法棧區中;但引用類型變量所引用的變量(包括數組、普通Java對象)則總是存儲在對內存中。

注意,引用變量本質上只是一個指針,只要程序通過引用變量訪問屬性,或通過引用變量來調用方法,該引用變量將會由它所引用的對象代替。

      3)、引用類型數組的初始化

引用類型數組的數組元素依然是引用類型的,因此數組元素裏存儲的還是引用,它指向另一塊內存,這塊內存裏存儲了該引用變量所引用的對象。例如:

class Student {

      public String name;

      public int number;

      public void output() {

             System.out.println(name + “,”+number);

}

}

public class Main{

      public static void main(String[] args) {

             Student[] stu = new Student[2];

             System.out.println(“數組長度:” + stu.length);

      Student xiaowu = new Student();

      xiaowu.name = “小武”;

      xiaowu.number = “41009160”;

      stu[0] = xiaowu;

      //下面兩行代碼所輸出的結果都是一樣的

      stu[0].output();

      xiaowu.output();

}

}

在上面的程序中,內存是這樣分配的:首先引用數組變量stu[]初始化完成後,內存中開闢出了長度爲二的空間用來存儲student對象;對引用變量xiaowu初始化完成後,內存中開闢了出了能夠存儲一個student對象長度的空間,用來存儲student對象;將xiaowu賦給stu[0],則在內存中數組stu[0]指向對象xiaowu

2、數組的使用

      當數組引用變量指向一個有效的數組對象之後,程序就可以通過該數組引用變量來訪問數組對象。Java語言不允許直接訪問對內存中的數據,因此無法直接訪問堆內存中的數組對象,程序將通過數組引用變量來訪問數據。

      要對數組有一個更深刻的認識,需要理解兩個關係:數組元素與變量間的關係、多維數組與變量間的關係。

      1)、數組元素與變量間的關係

             只要在已有數據類型之後增加括號,就會產生一個新的數組類型,例如:

      >int à int[]:在int類型後增加[]即變爲int[]數組類型

      >Stirng à String[]:在String類型後增加[]即變爲String[]數組類型

      當程序需要多個類型相同的變量來保存程序狀態時,可以考慮使用數組來保存這些變量。當一個數組初始化完成,就相當於定義了多個類型相同的變量。

      無論哪種類型的數組,其數組元素其實相當於一個普通變量,把數組類型之後的括號去掉之後得到的類型就是該數組元素的類型。

      從這個角度講,數組元素就是變量。

      注意,這裏的數組元素並不是指數組對象中的數組元素,而是指數組變量的數組變量元素。

      注意,main方法聲明的變量都屬於局部變量,因此它們都被保存在main方法棧中;但數組元素則作爲數組對象的一部分,總是保存在堆內存中,不管它們是基本類型的數組元素,還是引用類型的數組元素。

2)、多維數組與變量間的關係

      理解了數組元素與變量之間關係之後,如果已有的類型是int,在其後增加[]後得到一個數組類型;以int[]類型爲已有類型,在其後增加[]後得到int[][]依然是數組類型;

int[][]類型爲已有類型,在其後增加[]後得到int[][][]依然是數組類型。

      從上面可以看出,所謂多維數組,其實就是數組元素依然是數組的1維數組,2維數組是數組元素是1維數組的數組,3維數組是數組元素是2維數組的數組,4維數組是數組元素是3維數組的數組……N維數組是數組元素是N-1維數組的數組。

      所以,實際上我們可以這樣認爲:沒有多維數組,只有基本數據類型和引用數據類型。

 

綜上,數組的初始化有靜態初始化和動態初始化兩種;數組對象和數組變量不是同一個概念對於數組變量而言;數組元素的類型分爲基本類型的數組和引用類型的數組;所有局部變量都是存放在棧內存裏保存的,但引用類型變量所引用的對象則總是存儲在堆內存中;一定要區分它何時只是數組變量,何時代表數組對象本身;數組元素就是變量,沒有多維數組。

      

 

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