Integer 中你所不知道的

  • 2020 年 2 月 10 日
  • 筆記

前幾天和我六哥討論技術的時候說到了 Integer,大家可能覺得 Intger 有什麼好說的,不就是 int 嗎,Java 裝箱拆箱機制。那麼現在有這樣一個問題:

System.out.println(new Integer(1) == (new Integer(1)));  System.out.println(new Integer(1).equals(new Integer(1)));  System.out.println(Integer.valueOf(1) == Integer.valueOf(1));  System.out.println(Integer.valueOf(129) == Integer.valueOf(129));

這四行程式碼分別輸出什麼,為什麼? 答案:false、true、true、false

如果你沒答出來,那麼請繼續往下看吧~

IntegerCache

對,先說這個類,一看名字就知道是 Integer 快取,它是 Integer 的一個靜態內部類。源碼不多,先看程式碼:

private static class IntegerCache {      static final int low = -128;      static final int high;    // 這個值可以在vm屬性配置      static final Integer cache[];        static {          ... // 給 high 賦值,從 vm 屬性配置獲取配置值,默認 127            cache = new Integer[(high - low) + 1];          int j = low;          for(int k = 0; k < cache.length; k++)              cache[k] = new Integer(j++);            // range [-128, 127] must be interned (JLS7 5.1.7)          assert IntegerCache.high >= 127;      }  }

由上面源碼可以看出,IntegerCache 會快取值為 -128 ~ 127 的 Integer 對象,那麼什麼時候調用呢? 源碼中只有一個地方: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.valueOf 的時候,如果值在 -128 到 127 的範圍,就會使用 IntegerCache 中的快取對象。

解答

針對 new Integer(1) == (new Integer(1)),源碼沒有做特殊處理,就是 new 了兩個不同的對象,他們當然是不相等的,返回 false;

針對 new Integer(1).equals(new Integer(1)),可以看一下 Integer.equals() 函數的實現,函數內部是直接比較兩個對象的 value 是否相等,他們的 value 都是 1,所以返回 true;

針對 Integer.valueOf(1) == Integer.valueOf(1),就是我們前面提到的 IntegerCache 了,Integer.valueOf 會直接使用快取好的對象,兩個值相等,所以對象也是相同的,返回 true;

針對 Integer.valueOf(129) == Integer.valueOf(129),由於快取的範圍是 -128 ~ 127,值 129 顯然是超出範圍了,所以會 new 一個新對象,也不會相等,返回 false;

裝箱拆箱

再看一下以下輸出:

Integer i = 100;  Integer j = 100;  System.out.print(i == j);       //true

以上例子,Java 在編譯是會自動裝箱,編譯為:Integer i = Integer.valueOf(100),又看到了 valueOf,用了快取的 Integer,所以輸出 true。

Integer i = new Integer(100);  int j = 100;  System.out.print(i == j);       //true

以上例子,在 int 和 Integer 相比較時,Java 編譯器會自動把 Integer 拆箱為 int 類型,所以輸出 100。

拓展

好,看完了 Integer,我突然想起了其他的包裝器類會不會也是這樣,於是分別看了一下源碼。

我直接說結果吧,有興趣的同學可以看一下源碼:Long,Short 這兩個類,內部也快取了 -128 ~ 127 的對象,Boolean 內部快取了 TRUE、FALSE 兩個對象。和 Integer 類似,都是在調用 valueOf 方法的時候生效,new 的時候不會這樣。

作 者:ChanghuiN 原文鏈接:https://www.hchstudio.cn/article/2019/223d/ 版權聲明:非特殊聲明均為本站原創作品,轉載時請註明作者和原文鏈接。