數組的引用變量和內存分配


數組是一種引用類型,數組用來存儲同一種數據類型的數據,一旦初始化完成,即所占的空間就已固定下來,即使某個元素被清空,但其所在空間仍然保留,因此數組長度將不能被改變。

數組變量只有分配內存空間后才可以使用。

數組初始化分為靜態初始化(在定義時就指定數組元素的值,此時不能指定數組長度,否則就出現了靜態加動態混搭初始化數組了)

動態初始化(只指定數組長度,由系統分配初始值,初始值根據定義的數據類型來)。

不要出現靜態初始化跟動態初始化混搭比如new int[4]{1,3,4,5}

public class TestDemo {

    public static void main(String[] args) {
        //動態初始化
        int[] numbers = new int[4];
        numbers[0] = 1;
        for (int i : numbers) {
            System.out.println(i);
        }
        System.out.println("---------------");
        //靜態初始化
        numbers = new int[] {1,2,3,6};
        for (int i : numbers) {
            System.out.println(i);
        }
    }
}

數組引用變量是存放在棧內存(stack)中,數組元素是存放在堆內存(heap)中,通過棧內存中的指針指向對應元素的在堆內存中的位置來實現訪問,以下圖來說明數組此時的存放形式。

棧內存存放的是方法的內部定義的變量,當方法執行完成后,棧內存也就隨之消亡。而堆內存存放的一般是運行時的數據區以及創建一個對象的時候,對象是保存在堆內存,以便反復利用。當棧內存沒用引用變量引用該數據區的數據時,垃圾回收就會合適時間來回收。

package com.eminem.vo;
public class TestDemo {

    public static void main(String[] args) {
        int[] numbers = {3,4,5};
        
        int[] digits = new int[4];
        
        //把numbers的引用變量指向了digits的引用變量,此時的數組的長度就變成了3
        digits = numbers;
        
        System.out.println(digits.length);//3
        
        digits[3] = 6;
        System.out.println(digits.length);//java.lang.ArrayIndexOutOfBoundsException
        
    }
}

digits的長度從4變成3,那是棧內存指向了堆內存數據等於3長讀的數據。另外的4個數據就等待垃圾回收。

 

如果堆內存的數據元素也存放的是引用類型。此時數組元素存放引用,指向另外一快內存,在其中存放有效的數據。

package com.eminem.vo;

class Person{
    public int age;
    public String name;
    
    public void show(){
        System.out.println(name+"的年齡:"+age);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        //靜態定義一個數組
        Person[] persons;
        //分配內存空間
        persons = new Person[2];
        
        Person p1 = new Person();
        p1.age=10;
        p1.name="zs";
        
        Person p2 = new Person();
        p2.age=20;
        p2.name="ls";
        
        for (Person person : persons) {
            System.out.println(person);//null 由於還未給數組引用變量的null對象賦值
        }
        
        persons[0] = p1;
        persons[1] = p2;
        
        for (Person person : persons) {
            person.show();
        }
    }
}

分析如下:

也就是棧內存存放了對堆內存的引用,堆內存的數組元素又引用了其他內存。

package com.eminem.vo;

public class TestDemo {
    public static void main(String[] args) {
        //定義一個二維數組,一維是棧內存引用堆內存的數組元素,
        //二維是被棧引用的堆內存的數組元素的其中一個又去引用堆內存的其他數組元素
        int [][] numbers;
        
        numbers = new int[3][];//靜態初始化,長度為3的數組
        
        for (int i =0;i<numbers.length;i++) {
            System.out.println(numbers[i]);//null
        }
        
        System.out.println("---------");
        
        //棧內存引用堆內存的第一個數組元素又引用堆內存的其他數組元素
        numbers[0] = new int[2];
        
        //棧內存引用堆內存的第一個數組元素又引用堆內存的其他數組元素中的第二個元素1
        numbers[0][0] = 1;
        numbers[0][1] = 2;
        for (int i = 0; i < numbers[0].length; i++) {
            System.out.println(numbers[0][i]);
        }
        
        System.out.println("---------");
        
        numbers[2] = new int[3];
        numbers[2][0] = 5;
        numbers[2][1] = 6;
        numbers[2][2] = 7;
//        numbers[2][3] = 8; // 由於第三個數組元素引用堆內存的其他數組元素的長度為3,超過了 java.lang.ArrayIndexOutOfBoundsException
        
        for (int i = 0; i < numbers[2].length; i++) {
            System.out.println(numbers[2][i]);
        }
        
        System.out.println("---------");
        
//        numbers[3] = new int[1];// 由於numbers只定義了長度為3的數組元素 java.lang.ArrayIndexOutOfBoundsException
    }
}

數組工具類:Arrays類

package com.eminem.vo;

import java.util.Arrays;

public class TestDemo {
    public static void main(String[] args) {
        int[] a = {3, 4, 5, 6};
        int[] b = {3, 4, 5, 6};
        //比較a與b是否相等
        System.out.println(Arrays.equals(a, b));
        //查找4在a的位置
        System.out.println(Arrays.binarySearch(a, 4)); //1
        //拷貝a到c,並設c長度為6
        int[] c = Arrays.copyOf(a, 6); 
        System.out.println(c.length); //6
        //打印數組c
        System.out.println(Arrays.toString(c)); //[3, 4, 5, 6, 0, 0]
        
        //將a中的所有值賦值為1
        Arrays.fill(a, 1); 
        System.out.println(Arrays.toString(a));//[1, 1, 1, 1]
        //將c中的第三個到第五個賦值為2
        Arrays.fill(c, 2, 5, 2);
        System.out.println(Arrays.toString(c));//[3, 4, 2, 2, 2, 0]
        //快速排序c
        Arrays.sort(c);
        System.out.println(Arrays.toString(c)); //[0, 2, 2, 2, 3, 4]
    }
    
}

 

參考資料:

http://www.cnblogs.com/hmiinyu/archive/2012/10/22/2732781.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM