一、基礎概念
為了講清楚他們的差異,這里先介紹幾個概念。
1.1 常量池
所謂常量池:顧名思義就是用來存放一些常量的。該常量是在編譯期被確定,並被保存在已編譯的.class
文件中,其中包括了類,方法,接口等包含的數值常量,字符常量和字符串常量。
1.2 字符串常量池
在常量池中,有個專門用來存儲字符串常量的,稱之為字符串常量池。
當我們需要使用字符串時,首先會在該字符串常量中查找是否存在該字符串,若存在則直接進行使用;若不存在,則會新建一個對應的字符串,並保存在該字符串常量池中。
1.3 在編譯期間創建的常量和運行期間創建的常量保存的地址是不一樣的
對象的引用都是存放在棧中
- 編譯期間創建的常量保存在常量池中;
- 運行期間通過
new
創建時,會直接創建一個新字符串常量並會存儲在堆中。
所以我們可以發現,在堆中,可以有很多重復相同的字符串,而在常量池中,不會出現重復的值。
1.4 equals()
與==
==
- 如果是基本類型,
==
表示判斷它們值是否相等; - 如果是引用對象,
==
表示判斷兩個對象指向的內存地址是否相同。
equals()
equals()
方法未被重寫時(Object
時),比較的是內存地址;equals()
方法被String
、Integer
、Date
等類重寫時,其比較的是兩個內容是否相同。
二、String str=""
與new String()
的區別
2.1 String str=""
例如:
String str = "風塵博客";
- 先在棧區創建
str
引用,然后關於創建對象。
這個表達式,可能會創建一個對象,也可能不會創建對象。
- 如果常量池中沒有“風塵博客”這個字符串,就需要創建;
- 常量池中存在“風塵博客"這個字符串,就直接拿來用。
- 最后
str
指向常量池中的對象。
注意!這里就是上面說的,從常量池中直接取用,所以,兩者引用地址應該也相同,即
==
比較為true
。
2.2 String str=new String()
String str=new String(“風塵博客”)
- 同樣的,先在棧區創建
str
引用;
這個表達式,可能會創建一個對象,也可能創建兩個對象。
- 然后會直接創建一個字符串存放在堆中;
- 其次,同樣的:如果常量池中沒有“風塵博客”這個字符串,就需要創建;常量池中存在“風塵博客"這個字符串,就直接拿來用。
- 最后
str
指向常量池中的對象。
注意!這里這里和上面不一樣,這里直接在堆里創建對象,每新建一個都會創建一個,所以,兩者引用地址肯定不相同,即
==
比較為false
。