以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,而不应使用==,这可以避免出现奇怪的错误(不在缓存范围时失效)。