1、String str = new String("abc") 建立了幾個字元串對象?
答案:1個或者2個
Ⅰ 如果字元串常量池中已經有"abc"存在,這種情況隻需要建立 1 個對象,即 new 一個對象放在堆中。
Ⅱ 當字元串常量池中沒有 "abc",此時會建立如下 2 個對象:
一個是字元串字變量 "abc" 所對應的、駐留(intern)在字元串常量池中的執行個體,字元串常量池隻存放執行個體對象的引用。
另一個是通過 new String() 建立并初始化的,内容與"abc"相同的執行個體,在堆中。
總結: new String("xxx"); 如果字元串常量池intern中沒有對應的xxx 那麼就需要在字元串常量池建立,然後再在堆上new 一個對象。
2、String str1 = “abc” 和 String str2 = new String(“abc”)的差別?
兩者看似都是建立了一個字元串對象,但在記憶體中卻是不一樣的:
String str1= “abc” 在編譯期,JVM 會去字元串常量池來查找是否存在“abc”,如果不存在,就在字元串常量池中開辟一個空間來存儲“abc”;如果存在,就不用新開辟空間。然後在棧記憶體中開辟一個名字為 str1 的空間,來存儲 “abc” 在常量池中的位址值。
String str2 = new String("abc")在編譯階段 JVM 先去字元串常量池中查找是否存在 “abc”,如果過不存在,則在常量池中開辟一個空間存儲 “abc”。在運作時期,通過 String 類的構造器在堆記憶體中 new 了一個空間,然後字元串常量池中的 “abc”複制一份存放到堆空間中,在棧中為 str2 開辟空間,存放堆中 new 出來的這個 String 對象的位址值。
也就是說,前者在初始化的時候可能建立了一個對象,也可能一個對象也沒有建立;後者因為 new 關鍵字,至少在記憶體中建立了一個對象,也有可能是兩個對象。
3、Java中的128陷阱?
先來看一個例子:
public static void main(String[] args) {
Integer a=127,b=127;
Integer c=128,d=128;
System.out.println(a==b);// true
System.out.println(c==d);// false
}
為什麼出現這種情況呢?
我們都知道Integer 是 基本類型int 的包裝類型。
在Java設計之初,設計者認為,開發者可能經常用到的數字範圍都在100以内,而每次使用這些數字的包裝類型都要開辟新空間的話,可能會占用大量的資源。
是以他們規定在-128~127之間的Integer類型的變量,直接指向常量池中的緩存位址,不再使用new去開辟出新的空間。
執行 Integer c = 128,相當于執行:Integer c = Integer.valueOf(128),基本類型自動轉換為包裝類的過程稱為,自動裝箱(autoboxing)。
這也是出現上述代碼兩次比較結果不同的原因!下面我們看下valueOf() 源碼去體會下:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在Integer 中引入了IntegerCache 來緩存一定範圍的值,預設情況下範圍為:-128~127。
是以:上述代碼中的 127 命中了 IntegerCache,是以 a 和 b 是相同對象,而 128 則沒有命中,是以 c 和 d 是不同對象。
那麼,如果想要正确比較的話c與d的話,就需要拆箱比較,即在變量後加intValue()方法:
public static void main(String[] args) {
Integer a=127,b=127;
Integer c=128,d=128;
System.out.println(a==b);// true
System.out.println(c.intValue()==d.intValue());// true
}
可以直接記住下面的表格,道理都是一樣的:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iYiJWYxEWYyQWZmVjNwUWYlBTO0MTYiFWNxATM4YjNk9CX5d2bs92Yl1iclB3bsVmdlR2LcNWaw9CXt92Yu4GZjlGbh5yYjV3Lc9CX6MHc0RHaiojIsJye.png)