堆和棧都是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出來的對象,因此都放在堆區。
---------------------
作者:Devin_教主
來源:CSDN
原文:https://blog.csdn.net/qq_32053993/article/details/82812305