1. 程式人生 > >Java中堆和棧的區別在什麼地方?

Java中堆和棧的區別在什麼地方?

堆和棧都是Java用來在RAM中存放資料的地方。

(1)Java的堆是一個執行時資料區,類的物件從堆中分配空間。這些物件通過new等指令建立,通過垃圾回收器來銷燬。

(2)堆的優勢是可以動態地分配記憶體空間,需要多少記憶體空間不必事先告訴編譯器,因為它是在執行時動態分配的。但缺點是,由於需要在執行時動態分配記憶體,所以存取速度較慢。

1)棧中主要存放一些基本資料型別的變數(byte,short,int,long,float,double,boolean,char)和物件的引用

(2)棧的優勢是,存取速度比堆快,棧資料可以共享。但缺點是,存放在棧中的資料佔用多少記憶體空間需要在編譯時確定下來,缺乏靈活性。

舉例說明棧資料可以共享

String可以用以下兩種方式來建立:

String str1 = new String("abc");

String str2 = "abc";

第一種使用new來建立的物件,它存放在堆中。每呼叫一次就建立一個新的物件。

第二種是先在棧中建立物件的引用str2,然後查詢棧中有沒有存放“abc”,如果沒有,則將“abc”存放進棧,並將str2指向“abc”,如果已經有“abc”,則直接將str2指向“abc”。

下面用程式碼說明上面的理論

public class Demo {
	public static void main(String[] args) {
            String str1 = new String("abc");
            String str2 = new String("abc");
            System.out.println(str1 == str2);
	}
}

輸出結果為:false

public class Demo {
    public static void main(String[] args) {    
            String str1 = "abc";
            String str2 = "abc";
            System.out.println(str1 == str2);
	}
}

輸出結果為:true

因此,用第二種方式建立多個“abc”字串,在記憶體中其實只存在一個物件而已。這種寫法有利於節省記憶體空間。同時還可以提高程式的執行速度,因為JVM會自動根據棧中資料的實際情況來決定是否建立新物件。

程式碼一:

public class Demo {
	public static void main(String[] args) {    
		String s1 = "china";
		String s2 = "china";
		String s3 = "china";
		String ss1 = new String("china");
		String ss2 = new String("china");
		String ss3= new String("china");
	}
}

思考:分佈情況會怎樣?

思考:為什麼?

s1、s2、s3都是基本型別的區域性變數,

ss1、ss2、ss3都是String物件的引用,

所以都在棧區

而"china"是常量,

所以放在常量區

而三個new的物件,

自然就放在堆區

程式碼二:

class BirthDate{
	private int day;
	private int month;
	private int year;
	public BirthDate(int d, int m, int y) {
		day = d;
		month = m;
		year = y;
	}
	//省略get.set方法.
}
public class Test{
	public static void main(String[] arg) {
		int date = 9;
		Test test = new Test();
		test.change(date);
		BirthDate d1= new BirthDate(7,7,1970);
	}
	public void change(int i){
		i = 1234;
	}
}

思考:記憶體如何分佈?

思考:為什麼?

從執行程式碼部分看,

date, test, i, d1, d,m、y.

都屬於基本型別的區域性變數, 因此都分配到棧區。

而Test(),Birthdate()兩個都是new出來的物件,因此都放在堆區。