本文轉自:http://blog.csdn.net/dengshengjin2234/article/details/8471907
案例如下:
- public class StringTest {
- public static void main(String[] args) {
- String s = new String("abc");
- // 問題1:當類中執行String s = new String("abc");這行代碼後,在內存裏生成幾個對象?他們是什麼?在什麼地方?
- // (生成2個對象;首先去String
- // Pool查找有沒“abc”對象,沒有的話,就在池裏面放入abc,接着是new一個對象,是在堆裏面生成另一個對象;
- // s是引用,指向堆裏面的對象;)
- String s1 = "abc";
- // 問題2:當執行String s1 = "abc";這行代碼後,在內存裏生成幾個對象?他們是什麼?在什麼地方?
- // 答:一個對象也沒生成;s1引用string pool裏面的abc。
- String s2 = new String("abc");
- // 問題3:當類中執行String s2 = new String("abc");這行代碼後,在內存裏生成幾個對象?他們是什麼?在什麼地方?
- // 答:生成一個對象,首先是在String Pool查找,發現有“abc”,就不生成,接着在堆裏面生成一個對象;s2指向堆裏的“abc”
- // 執行完前三行語句,內存一個有三個對象,一個池裏面的,兩個堆裏面的;
- System.out.println(s == s1);// false
- System.out.println(s == s2);// false
- System.out.println(s1 == s2);// false
- // 對象的比較,是比較內存地址的,他們三個地址不同,都是輸出false
- // intern:
- // 調用該方法,JAVA虛擬機首先檢查字符串池中是否已經存在與該對象相等的對象存在,
- // 如果有則返回字符串池中對象的引用;如果沒有,則先在字符串池中創建一個相同值的String對象,然後返回他的引用。
- // 可以理解成比較他們的值是否相等
- System.out.println("s == s.intern()" + (s == s.intern())); // false,執行intern纔會創建s
- System.out.println(s1 == s1.intern());// true
- System.out.println(s == s2.intern());// true
- // intern如果pool存在,則指向它;
- String hello = "hello";
- String hel = "hel";
- String lo = "lo";
- System.out.println(hello == "hel" + "lo");// true,兩個都是在池裏面
- System.out.println(hello == "hel" + lo);// false,左邊是在池裏面,右邊是在堆裏面,當兩個都不是字面值(引號裏面、常量值)相加會生成新的對象
- System.out.println(hello == "hel" + lo);// false
- String hel_lo = ((hel + lo).intern());
- System.out.println("hello == hello.intern() " + (hello == hello.intern()));// true
- System.out.println(hello == hel_lo);// true
- System.out.println(hello == (hel + lo));// false
- }
- }
堆與棧的區別
- •棧(stack):主要保存基本類型(或者叫內置類型)(char、byte、short、int、long、float、double、boolean)和對象的引用,數據可以共享,速度僅次於寄存器(register),快於堆。
- •堆(heap):用於存儲對象。
CPU:寄存器
內存:主存儲器、ROM、RAM、高速緩存緩存器
JAVA數據存儲:寄存器、堆(new對象、垃圾回收等、Java堆可以處於物理上不連續的內存空間)、棧(RAM)、靜態存儲區域與常量存儲區域(靜態數據變量、常量)、非RAM(持久化的對象Serializable、對象轉化爲字符流發送到其他位置)
棧:Java虛擬機棧(OutOfMemoryError)(描述的是JAVA方法執行的內存模式,每個方法執行都會創建一個棧幀用於存儲局部變量表(存儲基本類型和對象引用)、操作棧、動態鏈接、方法出口)、本地方法棧(native)(StackOverflowError、OutOfMemoryError)
方法區:用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據
Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量池
(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後存放到方法區的運行時常量池中