java包装类型的缓存机制

Java中基本类型都有对应的包装类分别有:ByteShortIntegerLongFloatDoubleCharacterBoolean。而它们大部分都用到了缓存机制来提升性能。Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False

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
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() {}
}

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static class CharacterCache {
private CharacterCache(){}

static final Character cache[] = new Character[127 + 1];

static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}

public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}

Boolean缓存源码

1
2
3
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}

由源码可见,超出范围了仍然会创建对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
FloatDouble没有缓存机制

举例

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
Integer i1 = 33;
Integer i2 = 33;
/*直接是使用的缓存中的对象*/
System.out.println(i1 == i2);// 输出 true

Float i11 = 333f;
Float i22 = 333f;
/*Float没有缓存机制*/
System.out.println(i11 == i22);// 输出 false

Double i3 = 1.2;
Double i4 = 1.2;
/*Double没有缓存机制*/
System.out.println(i3 == i4);// 输出 false

Integer i5 = 127;
Integer i6 = new Integer(127);
/*i5是用的缓存中的对象,i6是直接创建的对象*/
System.out.println(i5 == i6); //输出false

Integer i7 = 128;
Integer i8 = new Integer(128);
Integer i9 = 128;
System.out.println(i7 == i8); //输出false
/*i7、i9超出 -128~127 的范围了,都是创建的对象*/
System.out.println(i7 == i9); //输出false

谨记: 所有包装类型之间的值比较,尽量都要用equals

参考链接:
Java Guide 包装类型的缓存机制了解么?


java包装类型的缓存机制
https://huajframe.github.io/2020/09/21/Java基础/Java包装类型的缓存机制/
作者
HuaJFrame
发布于
2020年9月21日
许可协议