Integer类源码剖析

Integer类源码剖析

一、Integer类的简介

Integer类是基元类型int的包装类,两者之间可以由编译器自动完成装箱拆箱,通过反编译后的代码不难看出,自动装箱对应于Integer.valueOf方法、自动拆箱对应于Integer.intValue方法。

image-20230915151801912

Integer继承了Number抽象类,实现了intValuelongValuefloatValuedoubleValuebyteValueshortValue等导出相应基元数值类型的方法,并且实现了Comparable接口。

image-20230915152247235

二、Integer类的字段

Integer类型是有符号整型,覆盖的范围是[-2^31^,2^31^-1],并且为了方便快速地解析数字字符串或者转换为字符串,预先定义了一些辅助数组如digitsDigitTensDigitOnessizeTable,后面讲到相关方法会再次谈到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 最小值:-2^31
public static final int MIN_VALUE = 0x80000000;
// 最大值:2^31 - 1
public static final int MAX_VALUE = 0x7fffffff;
// 基元类型int的Class对象
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
// 数字字符串中所有可能的字符,0~9加上a~z共36个,因此parseInt方法中的radix参数最大是36
static final char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
// 0~99所有数字的十位数字
static final byte[] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
// 0~99所有数字的个位数字
static final byte[] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
// 辅助求解数字字符串长度
static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
// 包装的int值
private final int value;
// 二进制补码的形式表示的int值的bit位数
public static final int SIZE = 32;
// 二进制补码的形式表示的int值的byte字节数
public static final int BYTES = SIZE / Byte.SIZE;

三、Integer类的构造方法

该构造方法创建一个新的表示特定int值的Integer对象,但是几乎不使用它而是静态工厂方法valueOf,因为其空间和时间性能都更佳。

1
2
3
4
@Deprecated(since="9")
public Integer(int value) {
this.value = value;
}

该构造方法创建一个新分配的Integer对象,该对象表示由String参数指示的int值。字符串完全按照基数10parseInt方法转换为 int值。

1
2
3
4
@Deprecated(since="9")
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}

四、Integer类的valueOf方法

valueOf方法返回持有由String参数表示的int值的Integer对象。其中String参数被解析为有符号十进制整数,等同于调用parseInt(String)方法,换句话说,该方法等价于Integer.valueOf(parseInt(s))

1
2
3
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}

valueOf方法返回持有由String参数表示的int值(基为参数radix)的Integer对象。其中String参数被解析为有符号radix进制整数,等同于调用parseInt(String,int)方法,换句话说,该方法等价于Integer.valueOf(parseInt(s,radix))

1
2
3
public static Integer valueOf(String s, int radix) throws NumberFormatException {
return Integer.valueOf(parseInt(s,radix));
}

valueOf方法使用到了IntegerCache,其[-128,127]范围内的Integer对象已预先创建完成作为缓存,因此我们推荐使用valueOf方法创建Integer对象。

1
2
3
4
5
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

五、Integer类的整数缓存

IntegerCache是Integer的静态内部类,主要完成常用范围(如[-128~127])内的Integer对象的缓存,可以提高Integer对象的构造性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private static class IntegerCache {
// 最低表示的整数
static final int low = -128;
// 最高表示的整数,可以由JVM参数控制
static final int high;
// Integer缓存数组
static final Integer cache[];

static {
// high value may be configured by property
// 默认缓存的Integer对象表示的最大值为127
int h = 127;
// 获取属性配置
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
// high的最小值是默认值127
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
// Integer缓存数组的长度不能超过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;
// 创建Integer缓存数组,范围是[low,high]
cache = new Integer[(high - low) + 1];
int j = low;
// Integer缓存数组初始化
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的存在,因此有必要注意以下测试代码的执行结果:

1
2
3
4
5
6
7
8
Integer i1 = 10;
Integer i2 = 10;
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1 == i2);
System.out.println(i1 == i3);
System.out.println(i3 == i4);
System.out.println(i3.equals(i4));

image-20230915161547171

六、Integer类的parseInt方法

image-20230915162109224

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public static int parseInt(String s, int radix)
throws NumberFormatException
{
/*
* WARNING: This method may be invoked early during VM initialization
* before IntegerCache is initialized. Care must be taken to not use
* the valueOf method.
*/
// 字符串参数为null,抛出NumberFormatException异常
if (s == null) {
throw new NumberFormatException("null");
}
// radix参数小于规定的最小基(2),抛出NumberFormatException异常
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
// radix参数大于规定的最大基(36),抛出NumberFormatException异常
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
// 是否为负数的标志
boolean negative = false;
// i表示字符参数的索引
int i = 0, len = s.length();
// 极值,注意即使传入正数字符串也会先求其相反数(负数),最后取反即可
// 对于正数:-Integer.MAX_VALUE
// 对于负数:Integer.MIN_VALUE
int limit = -Integer.MAX_VALUE;

if (len > 0) {
// 第一个字符可能是符号位
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
// 标记该字符串表示负数
negative = true;
// 极值为Integer.MIN_VALUE
limit = Integer.MIN_VALUE;
} else if (firstChar != '+') {
// 不合理的字符(如'#'),抛出NumberFormatException异常
throw NumberFormatException.forInputString(s);
}
// 如果字符串只有单个符号位,也会抛出NumberFormatException异常
if (len == 1) { // Cannot have lone "+" or "-"
throw NumberFormatException.forInputString(s);
}
// 字符串索引移动到有效数字位的开头
i++;
}
// 假如传入字符串是负数,limit=-2147483648,radix=10,那么multmin=-214748364
// multmin是循环计算result累积radix前的极限值,如果小于multmin如-214748365,那么累积radix后result=multmin*radix=-2147483650,超出了limit极值
int multmin = limit / radix;
int result = 0;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
// 当前索引代表的数值[0,radix-1]
int digit = Character.digit(s.charAt(i++), radix);
// 如果digit不正常或者字符串数字超出Integer的表示范围如3000000000,抛出NumberFormatException异常
if (digit < 0 || result < multmin) {
throw NumberFormatException.forInputString(s);
}
// 循环累积
result *= radix;
// 字符串数字超出Integer的表示范围如-2147483649,抛出NumberFormatException异常
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
// s="123",radix=10,计算公式result=((10*0+1)*10+2)*10+3
result -= digit;
}
// 如果传入正数字符串,计算结果是该正数的相反数,因此取反
return negative ? result : -result;
} else {
// 传入字符串参数为空字符串,抛出NumberFormatException异常
throw NumberFormatException.forInputString(s);
}
}

七、Integer类的toString系列

image-20230915171117915

注意:如果整形参数i是负数,处理过程中也当作无符号整数处理,最终返回的看作为无符号整数值2^32^+i

1
2
3
public static String toHexString(int i) {
return toUnsignedString0(i, 4);
}

image-20230915172747585

1
2
3
public static String toOctalString(int i) {
return toUnsignedString0(i, 3);
}

image-20230915172821570

1
2
3
public static String toBinaryString(int i) {
return toUnsignedString0(i, 1);
}

以上三个方法最终都会调用底层的toUnsignedString0方法,把传入的val参数当作无符号整型处理,输出省略不必要的前导零,计算出需要显示的字符个数后创建字节数组,从后往前根据val参数的shift位对应的字符填充字节数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private static String toUnsignedString0(int val, int shift) {
// assert shift > 0 && shift <=5 : "Illegal shift value";
// 需要显示的bit位数如对于0x000FFFFF来说,mag=32-12=20
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
// 需要的字符个数,最少是一个(0<=val<2^shift的情况)
int chars = Math.max(((mag + (shift - 1)) / shift), 1);
if (COMPACT_STRINGS) {
// 采用Latin1编码存储字符
byte[] buf = new byte[chars];
formatUnsignedInt(val, shift, buf, 0, chars);
return new String(buf, LATIN1);
} else {
// 采用UTF16编码存储字符
byte[] buf = new byte[chars * 2];
formatUnsignedIntUTF16(val, shift, buf, 0, chars);
return new String(buf, UTF16);
}
}

static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = (byte)Integer.digits[val & mask];
val >>>= shift;
} while (charPos > offset);
}

private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
val >>>= shift;
} while (charPos > offset);
}

测试代码如下:

1
2
3
4
5
6
7
System.out.println(Integer.toHexString(123));
System.out.println(Integer.toOctalString(123));
System.out.println(Integer.toBinaryString(123));
System.out.println(Integer.toHexString(-1));
System.out.println(Integer.toHexString(-2));
System.out.println(Integer.toHexString(0));
System.out.println(Integer.toHexString(1));

image-20230915173602765

八、Integer类的intValue系列

Integer类的导出基元数值类型的六个方法如下,注意byteValueshortValue可能会损失精度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public byte byteValue() {
return (byte)value;
}

public short shortValue() {
return (short)value;
}

public int intValue() {
return value;
}

public long longValue() {
return (long)value;
}

public float floatValue() {
return (float)value;
}

public double doubleValue() {
return (double)value;
}

九、Integer类的常用方法

image-20230915181328241

1
2
3
public String toString() {
return toString(value);
}

image-20230915181412827

1
2
3
4
5
6
7
public int hashCode() {
return Integer.hashCode(value);
}

public static int hashCode(int value) {
return value;
}

image-20230915181437317

1
2
3
4
5
6
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}