一、直接上圖
1.舉個例子
構造一個Person類
public class Person{
public String name;
public int age;
Person(String name,int age){
this.name = name;
this.age = age;
}
}
實例化person類
Person 張三 = new Person("張三",18);
- 引用變量 張三 (指向堆中張三實例的地址)儲存在棧中
- 張三實例(Person(“張三”,18))儲存在堆中,
- 張三的實例的class,本類(Person),加載後儲存在,方法區,
二、方法區的好處:提高性能。
1. 常量池
(1)避免重複的創建對象:銷燬對象而影響系統性能,實現對象的共享
(2)節省內存空間: 常量池的所有的相同的字符串的常量被合併,只佔用一個空間。
(3)節省運行時間:比較字符串時候, ( == ) 比 equals() 快,對於2個引用的變量,只用 ( == )
三、常用的面試題
1. String a = “str” 和 String b = new String(“str”) , a == b ?爲什麼?
回答:
a==b 是false的
- String a = “str” ; 會先在方法區的常量區找是否有字符串 “str”,有的話,直接把 方法區的常量區的"str"地址賦值給 a ,
沒有的話就在方法區的常量區開闢一塊空間,儲存 "str"並賦值"str"的地址給a,
所以無論如何a的地址是指向方法區的常量區的 - String b = new String(“str”)的 b的地址是指向堆空間的
2. String a2 = “hello” ,String b2 = “he”+“llo”; a == b ?爲什麼?
回答
a2 == b2 爲 true
b2 雖然爲動態拼接 但是所有的拼接成分都是已知的儲存在方法區的常量,這種拼接編譯器會自動幫你優化好。
但是如果
String a2 = “hello”
String c2 = new String(“llo”)
String b2 = “he”+c2;
a2 == b2 爲false;
因爲c2指向儲存在堆中的數據所以並不在方法區的常量區,b2會創建一個新的地址,鬼知道b2的地址在哪裏,只有運行的時候才知道。