Integer缓存机制分析

java的Integer缓存机制分析:

以Integer为例子介绍装箱和拆箱:”
装箱存在的情况:
int 赋值给Integer 即基本类型赋值给包装类型时

Integer i = 1; 等价于 Integer i = Integer.valueOf(1); java自动完成装箱操作

拆箱存在的情况:
int与Integer比较 及基本类型和包装类型比较时

Integer i = new Integer(1);
int j = 1;
i == j  //等价于 i.intValue() == j  i对象会自动拆箱int类型和j进行比较

Integer原理及缓存机制

Integer是int基本数据类型的包装类,无非是在int基本类型的基础上增加了一些操作和其他属性。

private final int value;//对应int基本类型的数值 是一个常量整型
 public int intValue() {
        return value;
 }

前面说过的装箱用到的一个方法是valueOf(),让我们看看源码:

//可以看到传入的i 先和IntegerCache比较 在IntegerCache中则返回IntegerCache中的Integer不存在则new一个Integer对象
 public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

IntegerCache实现如下:

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) {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low));
        }
        high = h;
        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }
    private IntegerCache() {}
}

知道Integer缓存的存在,下面我们看看下面的几个例子:
注:== 对象比较比较的是对象的引用是否相等 equals则根据对象内部的实现情况进行比较

Integer i = 1; //i = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
Integer j = 1; //j = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
System.out.println(i == j);//输出true  i 和j指向同一个对象 
Integer i = 1; //i = Integer.valueOf(1) 取缓存对象 IntegerCache.cache[129]
Integer j = new Integer(1); // 新创建一个对象
System.out.println(i == j);//输出false i 和j指向的不是同一个对象
Integer i = 128; //i = Integer.valueOf(128) 不在缓存访问内 new Integer(128)
Integer j = 128; //j = Integer.valueOf(128) 不在缓存访问内 new Integer(128)
System.out.println(i == j); //输出false i 和j指向的不是同一个对象 

所以Integer对象在比较是否相等的时候 不要用 == 用equals Integer内部实现了自己用equals,源码如下:

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
}

可以看出Integer缓存默认范围是-128<—>127,可以通过IntegerCache.high设置最大的范围。因为这部分是static的,所以在加载类是就会初始化Integer缓存,之后只要符合范围内所有Integer都是来自于这个缓存数组static final Integer cache[]。

总结:

可以看出我们在进行Integer值判定时,应使用equals,而不应使用==,这可以避免出现奇怪的错误(不在缓存范围时失效)。

你可能感兴趣的:(java基础)