Java-學習日記(100 == 100為true,1000 == 1000卻為false?)

Empirefree發表於2020-09-03

Integer底層設計

100 == 100為true,1000 == 1000卻為false?

之前也寫過String的==與equals的注意點,這次寫下Integer的底層設計,不妨先執行下下面程式碼:

Integer a = 1000, b = 1000;  
System.out.println(a == b);//1
Integer c = 100, d = 100;  
System.out.println(c == d);//2

基本知識:我們知道,如果兩個引用指向同一個物件,用 == 表示它們是相等的。如果兩個引用指向不同的物件,用 == 表示它們是不相等的,即使它們的內容相同。

這裡就涉及到Integer底層的IntegerCache.java,它快取了從 - 128 到 127 之間的所有的整數物件。

具體實現就是:當所有的小整數在內部快取,然後當我們宣告類似——

Integer c = 100;

實際做的是

Integer i = Integer.valueOf(100);

而內部valueof實現

public static Integer valueOf(int i) {
      if (i >= IntegerCache.low && i
          return IntegerCache.cache\[i + (-IntegerCache.low)\];
      return new Integer(i);
    }

如果值的範圍在 - 128 到 127 之間,它就從快取記憶體返回例項,C與D的引用其實都是指向同一物件,所以相同,而不再這個值得a,b就不從快取記憶體放回例項,所以不指向同一物件。

綜上所述:java中,像String,Integer這些不要用==進行比較,因為比較的是引用(基本資料型別除外),應該使用equals,這也符合sonarlint規範。

下面給出快取記憶體的魅力吧!

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

    Class cache = Integer.class.getDeclaredClasses()[0]; //1
    Field myCache = cache.getDeclaredField("cache"); //2
    myCache.setAccessible(true);//3

    Integer[] newCache = (Integer[]) myCache.get(cache); //4
    newCache[132] = newCache[133]; //5

    int a = 2;
    int b = a + a;
    System.out.printf("%d + %d = %d", a, a, b); // 2  +  2= 5;
}

相關文章