Android
的Surface
看的有点头晕,换个口味,下一篇再更java
偶然网上看到以下代码:数组
public class IntegerTest {
private Integer a = 100;
private Integer b = 100;
private Integer c = 200;
private Integer d = 200;
public static void main(String[] args) {
new IntegerTest().test();
}
public void test(){
System.out.println(a==b);
System.out.println(c==d);
}
}
复制代码
输出结果以下:缓存
true // 代表 a 和 b 是同一个对象
false // 代表 c 和 d 不是同一个对象
复制代码
你们可能已经知道这是关于Java
整数对象缓存(-128--127)的问题。markdown
咱们看下到底为何会这样spa
class
文件经过javap -c
命令将class
文件进行反汇编,内容以下:code
public class hua.lee.test.IntegerTest {
// 此处是编译后生成的对象初始化方法
public hua.lee.test.IntegerTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 100
7: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
10: putfield #3 // Field a:Ljava/lang/Integer;
13: aload_0
14: bipush 100
16: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
19: putfield #4 // Field b:Ljava/lang/Integer;
22: aload_0
23: sipush 200
26: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
29: putfield #5 // Field c:Ljava/lang/Integer;
32: aload_0
33: sipush 200
36: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
39: putfield #6 // Field d:Ljava/lang/Integer;
42: return
... // 省略部分
}
复制代码
以变量a
为例,它的核心赋值部分是:orm
4: aload_0
5: bipush 100
7: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
10: putfield #3 // Field a:Ljava/lang/Integer;
复制代码
invokestatic
是执行一个静态方法的指令,这里执行的是Integer.valueOf()
,也就是说对象
Java
的自动装箱其实就是编译器编译时将Integer a = 100;
转换为Integer a = Integer.valueOf(100);
的操做ip
Integer.valueOf()
Integer.valueOf()
的实现以下:ci
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
复制代码
能够看到
IntegerCache.low
和IntegerCache.high
之间的话,会返回IntegerCache.cache
数组中的Integer
对象new Integer()
IntegerCache
是Integer
的内部类,代码以下:
private static class IntegerCache {
// low 是写死的
static final int low = -128;
// 关于high,看样子是能够动态调整
static final int high;
// 用来缓存 Integer 对象的集合
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
// 从 java.lang.Integer.IntegerCache.high 属性中读取缓存的上限
String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
// 属性不为空,进行数值转换处理
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
// 不能小于 127
i = Math.max(i, 127);
// 肯定数组上限
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++);
// assert 保证上限 >= 127
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
复制代码
关于Integer
的缓存问题咱们就分析完了
Integer
缓存的下限是固定的-128
Integer
缓存的上限能够经过java.lang.Integer.IntegerCache.high
设置,可是必须>=127
Integer
在类初始化的时候就把缓存集合cahce
建立好了,而且在类初始化时会将cahce
集合填充完成