Java int 和 Integer 互轉原理

Yake1965 2022-01-07 20:18:49 阅读数:429

java int integer 原理

Java int 和 Integer 互轉

Documentation

Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.

自動裝箱(拆箱也是)是 Java 編譯器提供的原始類型和它的包裝類之間轉化的功能。
注意,自動裝箱和拆箱是 Java 編譯器的功能,並不是運行時的。

int 轉 Integer:

List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(i);
// Java 編譯器把上面的代碼轉換成了下面的樣子
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2)
li.add(Integer.valueOf(i));

反過來,Integer 轉 int:

public static int sumEven(List<Integer> li) {

int sum = 0;
for (Integer i: li)
if (i % 2 == 0)
sum += i;
return sum;
}
// 編譯器把上面的代碼轉化成了下面的樣子
public static int sumEven(List<Integer> li) {

int sum = 0;
for (Integer i : li)
if (i.intValue() % 2 == 0)
sum += i.intValue();
return sum;
}

Java 中 int 和I nteger 互轉,原理是 Java 編譯器幫你調用了包裝類的 valueOf() 和 intValue() 兩個方法。

Java Integer、int 與 new Integer()

所有整型包裝類對象之間的比較全部使用 equals 方法比較。

對於 Integer var = ? 在 -128 至 127 範圍內的賦值,Integer 對象是在 IntegerCache.cache 產生,會複用已有對象,這個區間內的 Integer 值可以直接使用 == 進行判斷,但是這個區間之外的所有數據,都會在堆上產生,並不會複用已有對象,所以推薦使用 equals 方法進行判斷。

  1. int 和 Integer 在進行比較的時候,Integer 會進行拆箱,轉為 int 值與 int 進行比較。
  2. Integer 與 Integer 比較的時候,由於直接賦值的時候會進行自動的裝箱。

IntegerCache 為 Integer 類的緩存類,默認緩存了 -128~127 的 Integer 值,如遇到 [-128,127] 範圍的值需要轉換為 Integer 時會直接從 IntegerCache 中獲取,具體如以下源碼:

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

當大於這個範圍的時候,直接 new Integer 來創建 Integer 對象。

new Integer(1) 和 Integer a = 1 ,前者創建對象,存儲在堆中,而後者是從 IntegerCache 中獲取的。那麼 Integer a = 128, 直接通過 new Integer(128)創建對象,進行裝箱。

public class Test {

public static void main(String[] args) {

Integer i = new Integer(128);
Integer i2 = 128; // 自動裝箱
// == 比較對象的地址是不是相同
System.out.println(i == i2); // false
Integer i3 = new Integer(127);
Integer i4 = 127;
System.out.println(i3 == i4); // false
Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6); // false
Integer i7 = 127;
Integer i8 = 127;
System.out.println(i7 == i8); // true
}
}

Integer.valueOf() new Integer()

當你需要產生一個整形的包裝類的實例的時候(比如整數10),有兩種方式:
第一種,使用構造函數 new 一個對象:

Integer i = new Integer10);// 已過時,且標記為待删除。

第二種,使用靜態工廠方法產生實例:

Integer i = Integer.valueOf(10);

當你用第一種方式時每次都會產生一個新的實例,而當你使用靜態工廠方法時,不一定會產生一個新的實例,注意我說的是不一定,至少這裏沒有產生一個新的實例。

當你產生的數是 -128 到127時,不會 new 一個新的對象,超過這個範圍時,同樣是 new 一個新的對象。

為什麼 Java 9 不建議使用 new Integer 了?

java.lang.Integer @Deprecated(since = “9”)
@Contract(pure = true)

It is rarely appropriate to use this constructor. The static factory valueOf(int) is generally a better choice, as it is likely to yield significantly better space and time performance.

最後一句不說說了嗎,有更好的空間和時間性能,你用new 也沒事。

@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

上面是 valueOf, 當你傳入小於 128 的值時,返回的是內置的緩存值,節省空間和效率。

版权声明:本文为[Yake1965]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201072018492961.html