棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、double、float、boolean)和對象的引用,數據可以共享,速度僅次於寄存器(register),快於堆。
方法區(method area):static final 修飾的成員變量都存儲於方法區中,如常量池。
堆(heap):用於存儲對象實例及數組。
方法區:
以String 類型來舉例:
1 String s1="abc"; 2 String s2="abc"; 3 String s3=new String("abc"); 4 System.out.println("s1和s2 引用地址是否相同:"+(s1 == s2)); //true 5 System.out.println("s1和s2 值是否相同:"+s1.equals(s2)); //true 6 System.out.println("s1和s3 引用地址是否相同:"+(s1 == s3)); //false 7 System.out.println("s1和s3 值是否相同:"+s1.equals(s3)); //true
內存結構圖如下:
s1 和 s2 地址引用值相等,說明 s1 和 s2 引用的是同一個對象的地址,s3 與 s1 地址引用不等,說明 s3 與其他兩個引用的不是同一個地址。
java為了避免產生大量的String對象,設計了一個字符串常量池(存在內存中的方法區里)。工作原理是這樣,創建一個字符串時,JVM首先會檢查字符串常量池中是否有值相等的字符串,如果有,則不再創建,直接返回該字符串的引用地址,如果沒有,則創建,然后放到字符串常量池中,並返回新創建的字符串的引用地址,所以上面s1==s2結果為true。
而 s3 不同的是,JVM首先是在字符串常量池中找 "abc" 字符串,如果沒有則創建字符串常量,如果有則不需要創建;當遇到 new 時,還會在堆內存里面創建一個新的 String 對象,存儲 “abc” ,並將堆內存上String 對象引用的地址返回,所以 s3 與 s1 、s2 引用的不是同一個字符串地址。
本文參考:https://www.cnblogs.com/marsitman/p/11248001.html
版權聲明:本文版權歸作者所有,歡迎轉載,但請注明出處。