Java包裝類之Integer的 "==" 判斷數值是否相等的陷阱及緣由分析

在很久之前的一次面試中,面試官問了我這麼一個問題:「如今有 Integer a = 56, b = 56, c = 180, d = 180;  請問:a == b ,c == d  是否成立,也就是是否爲true?」java

我當時知道 a == b 是 爲true,c == d 是爲false的,我也是這麼回答的。接着面試官問我,「爲何呢?」面試

而後我就不知道了。那個的確是否是很清楚爲何會這樣,不過雖然那個時候這個問題沒有回答出來,可是其餘問題都回答得不錯,而且這是一面,到了二面的時候也回答得不錯,因此最後仍是拿下來了這個offer。數組

雖然那個時候拿到了offer,可是沒有回答出這個問題,我仍是挺在乎的,後面我也去研究了一下。緩存

首先我經過代碼驗證一下我那次面試的回答:ide

1 //定義兩組Integer變量
2 Integer a = 56, b = 56, c = 180, d = 180;
3 System.out.println("a == b:" + (a == b));
4 System.out.println("c == d:" + (c == d));

打印結果以下:ui

1 a == b:true
2 c == d:false

接下來咱們來找一下到底爲何?this

當咱們按照  :spa

1 Integer a = 56, b = 56, c = 180, d = 180; 

定義變量的時候其實就至關於:code

1 Integer a = Integer.valueOf(56), b = Integer.valueOf(56), c = Integer.valueOf(180), d = Integer.valueOf(180);

咱們去看 Integer.valueOf() 的源碼:orm

 1     /**
 2      * Returns an {@code Integer} instance representing the specified
 3      * {@code int} value.  If a new {@code Integer} instance is not
 4      * required, this method should generally be used in preference to
 5      * the constructor {@link #Integer(int)}, as this method is likely
 6      * to yield significantly better space and time performance by
 7      * caching frequently requested values.
 8      *
 9      * This method will always cache values in the range -128 to 127,
10      * inclusive, and may cache other values outside of this range.
11      *
12      * @param  i an {@code int} value.
13      * @return an {@code Integer} instance representing {@code i}.
14      * @since  1.5
15      */
16     public static Integer valueOf(int i) {
17         if (i >= IntegerCache.low && i <= IntegerCache.high)
18             return IntegerCache.cache[i + (-IntegerCache.low)];
19         return new Integer(i);
20     }

有以上的源碼和註釋中會發現從jdk1.5開始就有了這個方法,當傳入的參數"i"大於等於 IntegerCache.low 且小於等於IntegerCache.high 的時候返回 IntegerCache.cache[i + (-IntegerCache.low)],不然 new 一個Integer變量返回,顧名思義IntegerCache 應該就是Integer的緩存用的相關靜態類,這個時候咱們能夠繼續去看 IntegerCache 的源碼:

 1     /**
 2      * Cache to support the object identity semantics of autoboxing for values between
 3      * -128 and 127 (inclusive) as required by JLS.
 4      *
 5      * The cache is initialized on first usage.  The size of the cache
 6      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 7      * During VM initialization, java.lang.Integer.IntegerCache.high property
 8      * may be set and saved in the private system properties in the
 9      * sun.misc.VM class.
10      */
11 
12     private static class IntegerCache {
13         static final int low = -128;
14         static final int high;
15         static final Integer cache[];
16 
17         static {
18             // high value may be configured by property
19             int h = 127;
20             String integerCacheHighPropValue =
21                 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
22             if (integerCacheHighPropValue != null) {
23                 try {
24                     int i = parseInt(integerCacheHighPropValue);
25                     i = Math.max(i, 127);
26                     // Maximum array size is Integer.MAX_VALUE
27                     h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
28                 } catch( NumberFormatException nfe) {
29                     // If the property cannot be parsed into an int, ignore it.
30                 }
31             }
32             high = h;
33 
34             cache = new Integer[(high - low) + 1];
35             int j = low;
36             for(int k = 0; k < cache.length; k++)
37                 cache[k] = new Integer(j++);
38 
39             // range [-128, 127] must be interned (JLS7 5.1.7)
40             assert IntegerCache.high >= 127;
41         }
42 
43         private IntegerCache() {}
44     }

有上面的源代碼能夠看出,在Integer裏定義了一個私有的靜態內部類 IntegerCache ,在其中定義了 靜態Integer數組 cache ,長度爲 high = 127 和 low = -128  之間的差值,而且存儲的是 從 low到high,即-128到127的值。 

總結:

由以上的分析咱們能夠知道,當咱們  Integer a = 56, b = 56, c = 180, d = 180; 的時候:

1. 若是定義的變量在 -128到127之間,則是直接去緩存cache裏的值,因此若是數值一致則對應的地址值也會一致,因此咱們用 == 判斷兩個值是否相等,是返回 true的;

2. 若是定義的變量不在  -128到127之間,則經過new Integer(int i)的方式建立數值,而且每次都會從新new一個對象,這就致使每次的對象的數值即便同樣可是地址值不一致,因此此時用 == 判斷兩個值是否相等就不如咱們所願了;

3. 因此咱們遇到包裝類 Integer定義的變量的時候,若是要判斷兩個變量的值是否相等,則使用 equals來判斷,儘可能不要用 == 的來判斷。

相關文章
相關標籤/搜索