從源碼看java中Integer的緩存問題


在開始詳細的說明問題之前,我們先看一段代碼

1 public static void compare1(){
2         Integer i1 = 127, i2 = 127, i3 = 128, i4 = 128;
3         System.out.println(i1  == i2);
4         System.out.println(i1.equals(i2));
5         System.out.println(i3  == i4);
6         System.out.println(i3.equals(i4));
7     }

這段代碼輸出的結果是什么呢?

答案是:

是不是感到奇怪呢?為什么127的時候==是true,128的時候就變成了false?其實要回答這個問題不難。

Integer在賦值的時候會發生自動裝箱操作,調用Integer的valueOf方法,那么我們看一下java的源碼(1.8):

 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     }

這里根據源碼可以看出,在傳入的i值在IntegerCache.low和IntegerCache.high之間的時候,會返回IntegerCache.cache數組里面的數,不在這個范圍才會new一個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     }

我們看到IntegerCache的low定義為-128,high默認定義為127.但是high是可以配置的,如果沒有配置才是127.我們不去看配置的情況,因為java默認是沒有配置的。看一下cache數組,長度為high-low+1,從-128開始到127,存在cache數組內。

從上面的代碼中可以看出,java在申請一個大於-128小於127的數時,其實是從cache中直接取出來用的,如果不在這個范圍則是new了一個Integer對象。

對於==,他比較的是地址。對於int來說比較的是值。

對於equals,比較的是內容(要看equals的具體實現)。看一下Integer里面的實現:

 1 /**
 2      * Compares this object to the specified object.  The result is
 3      * {@code true} if and only if the argument is not
 4      * {@code null} and is an {@code Integer} object that
 5      * contains the same {@code int} value as this object.
 6      *
 7      * @param   obj   the object to compare with.
 8      * @return  {@code true} if the objects are the same;
 9      *          {@code false} otherwise.
10      */
11     public boolean equals(Object obj) {
12         if (obj instanceof Integer) {
13             return value == ((Integer)obj).intValue();
14         }
15         return false;
16     }

它比較的確實是值的大小。

因此i1==i2和i1.equals(i2)都是true

i3==i4為false

i3.equals(i4)為true。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM