天天看點

Java中的128陷阱和new String(“xxx“)建立了幾個對象問題

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
}
      

可以直接記住下面的表格,道理都是一樣的:

Java中的128陷阱和new String(“xxx“)建立了幾個對象問題