【JDK】分析 String str=「「 與 new String()

一、基礎概念

為了講清楚他們的差異,這裡先介紹幾個概念。

1.1 常量池

所謂常量池:顧名思義就是用來存放一些常量的。該常量是在編譯期被確定,並被保存在已編譯的.class文件中,其中包括了類,方法,介面等包含的數值常量,字元常量和字元串常量。

1.2 字元串常量池

在常量池中,有個專門用來存儲字元串常量的,稱之為字元串常量池。

當我們需要使用字元串時,首先會在該字元串常量中查找是否存在該字元串,若存在則直接進行使用;若不存在,則會新建一個對應的字元串,並保存在該字元串常量池中。

1.3 在編譯期間創建的常量和運行期間創建的常量保存的地址是不一樣的

對象的引用都是存放在棧中

  1. 編譯期間創建的常量保存在常量池中;
  2. 運行期間通過new創建時,會直接創建一個新字元串常量並會存儲在堆中。

所以我們可以發現,在堆中,可以有很多重複相同的字元串,而在常量池中,不會出現重複的值。

1.4 equals()==

  • ==
  1. 如果是基本類型,==表示判斷它們值是否相等;
  2. 如果是引用對象,==表示判斷兩個對象指向的記憶體地址是否相同。
  • equals()
  1. equals()方法未被重寫時(Object時),比較的是記憶體地址;
  2. equals()方法被StringIntegerDate等類重寫時,其比較的是兩個內容是否相同。

二、String str=""new String()的區別

2.1 String str=""

例如:

String str = "風塵部落格";
  • 先在棧區創建str引用,然後關於創建對象。

這個表達式,可能會創建一個對象,也可能不會創建對象。

  1. 如果常量池中沒有「風塵部落格」這個字元串,就需要創建;
  2. 常量池中存在「風塵部落格”這個字元串,就直接拿來用。
  • 最後str指向常量池中的對象。

注意!這裡就是上面說的,從常量池中直接取用,所以,兩者引用地址應該也相同,即 == 比較為true
JDK-String-compare-01

2.2 String str=new String()

String str=new String(「風塵部落格」)
  • 同樣的,先在棧區創建str引用;

這個表達式,可能會創建一個對象,也可能創建兩個對象。

  1. 然後會直接創建一個字元串存放在堆中;
  2. 其次,同樣的:如果常量池中沒有「風塵部落格」這個字元串,就需要創建;常量池中存在「風塵部落格”這個字元串,就直接拿來用。
  • 最後str指向常量池中的對象。

注意!這裡這裡和上面不一樣,這裡直接在堆里創建對象,每新建一個都會創建一個,所以,兩者引用地址肯定不相同,即 == 比較為false

JDK-String-compare-02

Tags: