1. 程式人生 > >Java 中的Integer Pool 和 autoboxing-same-value-to-different-objects問題

Java 中的Integer Pool 和 autoboxing-same-value-to-different-objects問題

1. 遇到問題

昨天刷題的時候遇到一個很有趣的整數比較的問題, 整理如下:
(1)

    int i = 127;
    int j = 127;
    System.out.println(i == j);
    int i = 128;
    int j = 128;
    System.out.println(i == j);

這兩個輸出應該都是true,沒有問題。
(2)

    Integer i = 127;
    Integer j = 127;
    System.out.println(i == j);
    Integer i = 128
; Integer j = 128; System.out.println(i == j);

第一個輸出的是true, 第二個輸出的是false, 這裡就比較有意思了,哈哈~
(3)

    Integer i = new Integer(127);
    Integer j = new Integer(127);
    System.out.println(i == j);
    Integer i = new Integer(128);
    Integer j = new Integer(128);
    System.out.println(i == j);

這兩個輸出的都是false, emmmmmmmmmm, 是不是有點懵圈。。。。。


2. 解決問題

首先,應該知道java中的自動裝箱和自動拆箱機制。簡而言之,就是在Java中,jvm會自動實現基本資料型別和與之相對應的類的之間的自動轉換。例如int和Integer之間能夠自由的轉換。

其次,應該明白物件之間用“==”比較,比較的是記憶體中的物件是否一樣(可以理解為地址是否一樣)。

然後,對於第一種情況,兩個int之間的比較,比較的是數值,符合我們的常規認識。 對於第二種情況,127之間的比較返回true, 128之間的比較返回false,是因為jvm中包含一個整數池(pool of Integer values ) ,這個Integer Pool只包含-128 - 127。所以當建立一個-128到127之間的Integer時,會自動引用池中的物件,故127之間的比較返回true,而建立小於-128或大於127的Integer時,則會另外單獨建立,所有兩個128是不同的物件,他們之間的比較自然返回false。對於第三種情況,採用 new關鍵字建立整數物件時,會在記憶體中建立不同的物件,所以這種情況下,不管value大小,他們之間的比較必然返回false。


3.總結

(1)整數之間直接用“==”比較大小,可能會出現autoboxing-same-value-to-different-objects問題;
(2)int之間用”==”比較,比較的是二者值是否相同;
(3)jvm中有一個Integer Pool,包含-128 - 127之間的整數物件。當採用直接賦值的方法建立Integer時,能用池中物件直接表示的,會繼續引用池中的物件,超出範圍的才會建立新的物件(這也是jvm節省記憶體空間的一種策略);
(4)採用new關鍵字建立Integer物件時,會建立新的物件,而不是引用整數池中的物件。


4. Objects.equals()方法

嘗試了一下,不用“==”進行上述的比較,而用Objects.equals()方法進行上述的比較。

    int i1 = 127;
    int j1 = 127;
    System.out.println(Objects.equals(i1, j1));

    int i2 = 128;
    int j2 = 128;
    System.out.println(Objects.equals(i2, j2));

    Integer i3 = 127;
    Integer j3 = 127;
    System.out.println(Objects.equals(i3, j3));

    Integer i4 = 128;
    Integer j4 = 128;
    System.out.println(Objects.equals(i4, j4));

    Integer i5 = new Integer(127);
    Integer j5 = new Integer(127);
    System.out.println(Objects.equals(i5, j5));

    Integer i6 = new Integer(128);
    Integer j6 = new Integer(128);
    System.out.println(Objects.equals(i6, j6));

上述結果輸出的都是true, 如何理解呢?emmmmmmmmm……….
先看Objects.equals方法的說明:

Returns true if the arguments are equal to each other and false otherwise. Consequently, if both arguments are null, true is returned and if exactly one argument is null, false is returned. Otherwise, equality is determined by using the equals method of the first argument.

所以這個方法會呼叫第一個引數的equals方法,上述例子中也就是呼叫Integer的equals方法。而Integer的equals方法比較的是兩個整數的int value值是否相同,故返回true。


5. 參考資料

http://www.devx.com/tips/Tip/42276