IntegerCache是Integer中的静态类,用于构建[-128,127]的数组缓存
//首先,它是Integer的一个静态内部类
private static class IntegerCache {
//[-128,high]
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
// high 默认为127
int h = 127;
// 这里会从启动配置中读取配置,设置最大缓存长度
// 缓存的大小可以通过该 -XX:AutoBoxCacheMax=<size> 选项控制
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
// 这里和127比较,Math.max(a,b)方法 a>=b时,都会取a
// 这里的目的是为了控制最大值为127(数组下标从0开始,所以ingeger[127]放的是127)
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
// (a,b)-> a<=b 取a
// 这里是为了保障 不会超过数组长度 2^32-1 [-128,2^32-128-1] 最大的数组长度是 2^32 - 1
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;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
// 算出数组的长度length 因为数组长度要比实际的数字大1,所以+1
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
// 判断archivedCache是不是为空,构架的时候,size是不是大于缓存的长度
if (archivedCache == null || size > archivedCache.length) {
//创建一个size长度的数组 对应 int size = (high - low) + 1;
Integer[] c = new Integer[size];
int j = low;
// 根据size的长度进行循环写入数据到数组,起始值从low开始
// 这里就能看出来 数组是[-128,-127,-126]
// [0] = -128, [1] = -127, [2] = -126
for(int k = 0; k < c.length; k++)
c[k] = new Integer(j++);
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
结论
比较Integer类型对象是否相同,不要用==,==和!= 比较的是对象的引用,最好用方法里的equals()方法,因为==比较的是引用,当你的数字是[-128,high]时,Ingeger会先从IntegeCache里面取值
笔记
IntegeCache 可以通过 -XX:AutoBoxCacheMax= 选项high大小
比较大小后取值,可以用 Math.max(a,b) 和 Math.min(a,b)
断言关键字的使用,需要配置 VM options才会生效 -ea, 默认是不生效的
assert IntegerCache.high >= 127;
比较float类型时,不要使用==,Float类型时不要用equals(),会有精度问题 简单来说,就是float运算的过程中,四舍五入后,难免会有超低的精度偏差 比如 1.1 和 1.10000000001,是运算时出现的
public static void main(String[] args) {
float x= 0.0f;
for (int i = 0; i < 11; i++) {
x+=0.1f;
}
float y= 0.1f*11;
//1.1000001
System.out.println(x);
//1.1
System.out.println(y);
//false
System.out.println(x==y);
}
上面的代码中,一个是0.1+11次,一个是0.1*11,运算结果,应该是一致的,却出现了精度的偏差(具体为毛还不清楚),所以运算完直接 用==或者equals()比较数据是不准确的 针对这种情况,我们可以用BigDecimal去处理数据
BigDecimal 是不可变的,能够精确地表示十进制数字。需要注意的是,创建 BigDecimal 对象时,要使用参数为 String 的构造方法,不要使用构造参数为 double 的,如果非要使用 double 创建,一定要用 valueOf 静态方法,防止丢失精度。然后调用 compareTo 方法比较即可