Integer
本文源碼基于JDK8
Integer也是我們經(jīng)常使用的工具類、包裝類,此文主要用于記錄學(xué)習(xí)筆記,主要從源碼角度深入了解一下。
public final class Integer extends Number implements Comparable<Integer> {
// 2147483647
public static final int MIN_VALUE = 0x80000000;
// -2147483648
public static final int MAX_VALUE = 0x7fffffff;
// 獲取基本類型int類型是class
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
}
說(shuō)明:Integer.TYPE == int.class // true
- 繼承Number類
Number類中只有構(gòu)造方法和幾個(gè)抽象方法:
構(gòu)造方法
public Integer(int value) {
this.value = value;
}
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
自動(dòng)裝箱和自動(dòng)拆箱
JDK1.5之后,java提供了自動(dòng)裝箱和自動(dòng)拆箱的功能,下面從源碼角度分析下Integer的裝箱:
package com.quancheng;
public class ClassTest {
public static void main(String[] args) throws InterruptedException {
Integer num = 10;
}
}
通過(guò)javap -v ClassTest.class查看字節(jié)碼,可以看出自動(dòng)裝箱實(shí)際是JVM編譯器幫我們做的工作,調(diào)用的是Integer.valueOf()方法
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=2, args_size=1
0: bipush 10
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: return
分析到這里可以看出,實(shí)際上Integer a = 100 等價(jià)于Integer a = Integer.valueOf(100);只不過(guò)這個(gè)工作是JVM幫我們做的;
自動(dòng)拆箱:
public static void main(String[] args) throws InterruptedException {
int num = new Integer(11);
}
對(duì)應(yīng)的字節(jié)碼指令:
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #2 // class java/lang/Integer
3: dup
4: bipush 11
6: invokespecial #3 // Method java/lang/Integer."<init>":(I)V
9: invokevirtual #4 // Method java/lang/Integer.intValue:()I
12: istore_1
13: return
通過(guò)分析可以發(fā)現(xiàn),自動(dòng)拆箱實(shí)際是編譯器調(diào)用了Integer.intValue()的方法完成的轉(zhuǎn)換
重點(diǎn)方法
-
valueOf方法
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }IntegerCache是一個(gè)靜態(tài)內(nèi)部類,主要用于緩存low - high之間數(shù)字的包裝類
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; 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; } private IntegerCache() {} }上面的源碼中可以看出IntegerCache有三個(gè)被final修飾的靜態(tài)filed外加一個(gè)靜態(tài)塊和一個(gè)私有的構(gòu)造器;很簡(jiǎn)單很普通的一個(gè)類,被緩存的包裝類就介于low - high之間,low的值已經(jīng)寫死-128,而high的值由你的虛擬機(jī)決定sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"),既然是一個(gè)參數(shù)也就意味著你可以動(dòng)態(tài)設(shè)置,具體怎么設(shè)置自行百度。然后在循環(huán)中將low - high之間數(shù)字的裝箱后方法cache[]這個(gè)Integer類型的數(shù)組中。這樣就完成了緩存
在日常編碼中,我們需要注意Integer緩存的問(wèn)題
Integer a = 100;
Integer b = 100;
Integer f = Integer.valueOf(100);
Integer c = 200;
Integer d = 200;
System.out.println(a == b);//true
System.err.println(a == f); // true
System.out.println(c == d);//false
- stringSize(int x)
這個(gè)方法很有意思,我覺(jué)得可以單獨(dú)看看這個(gè)方法,主要作用就是判斷一個(gè)數(shù)字的位數(shù),但是運(yùn)用的非常巧妙
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// Requires positive x
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
- equals(Object obj)
需要注意的是Integer也重寫了equals(Object obj),故若比較的值類型都是Integer時(shí),equals()和==作用是相同的
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
我們可以寫個(gè)例子測(cè)試下:
Integer num = new Integer(999);
System.err.println(num ==999);
public static void main(java.lang.String[]) throws java.lang.InterruptedException;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #2 // class java/lang/Integer
3: dup
4: sipush 999
7: invokespecial #3 // Method java/lang/Integer."<init>":(I)V
10: astore_1
11: getstatic #4 // Field java/lang/System.err:Ljava/io/PrintStream;
14: aload_1
15: invokevirtual #5 // Method java/lang/Integer.intValue:()I
18: sipush 999
21: if_icmpne 28
24: iconst_1
25: goto 29
28: iconst_0
29: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
32: return
可以看出實(shí)際上是先拆箱再比較值