记得当初老师告诉我们,尽量用Integer来定义int型字段,因为这样可以防止个别情况出现给int字段赋值null时引起的报错,我觉得有道理,就照做了相信有很多人在对两个Integer型数字判断相等时跟我一样使用“==”号吧,下面给大家看一个神奇的现象:,今天小编就来聊一聊关于integer是不是合法的关键字?接下来我们就一起去研究一下吧!
integer是不是合法的关键字
记得当初老师告诉我们,尽量用Integer来定义int型字段,因为这样可以防止个别情况出现给int字段赋值null时引起的报错,我觉得有道理,就照做了。相信有很多人在对两个Integer型数字判断相等时跟我一样使用“==”号吧,下面给大家看一个神奇的现象:
Integer integera = 1;
Integer integerb = 1;
Integer integerc = 127;
Integer integerd = 127;
Integer integere = 128;
Integer integerf = 128;
System.out.println("integera==integerb:" (integera == integerb));
System.out.println("integerc==integerd:" (integerc == integerd));
System.out.println("integere==integerf:" (integere == integerf));
运行结果:
integera==integerb:true
integerc==integerd:true
integere==integerf:false
刚开始我满脸疑惑,为什么1可以,127可以,128就不行了呢,与其想破脑袋没有结果,还不如深入源码一探究竟,于是乎我找到了Integer的源码,发现Integer类里面竟然隐藏了一个内部类,是不是这小子搞的鬼呢?
// 如果没看错的话,这个内部类应该跟缓存有关吧
private static class IntegerCache {
static final int low = -128; // 最小值-128
static final int high; // 最大值
static final Integer cache[]; // 缓存数组
// 静态块初始化缓存数组
static {
// 先设置一个默认最大值为127
int h = 127;
// 从启动VM参数-Djava.lang.Integer.IntegerCache.high 获取自定义设置的Integer缓存最大值
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
// 如果设置了Integer缓存最大值的情况
if (integerCacheHighPropValue != null) {
try {
// 将Integer缓存最大值转成int
int i = parseInt(integerCacheHighPropValue);
// 跟127比较取大值,也就是你自定义的最大值只有大于127的时候才会生效
i = Math.max(i, 127);
// Integer.MAX_VALUE - (-low) -1 意思是数组的最大长度减去128个负数,再减去一个0,剩下的数跟上面计算过的最大值比较取小作为缓存的最大值
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];
// j初始值为最小值-128
int j = low;
// 循环把最小值到最大值之间的数字通过构造方法生成Integer对象并按照从小到大的顺序放到缓存数组中
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() {}
}
哦,看明白了,原来是初始化的时候把-128到127(可以通过vm启动参数调整)之间的所有数字创建Integer对象放到缓存数组中了啊,再来看下面的这段代码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i (-IntegerCache.low)];
return new Integer(i);
}
获取Integer对象的时候,只要你传的值在-128到127之间,就直接从缓存中取出Integer对象返回,否则,会new新的Integer对象,到这里我恍然大悟,“ == ”号比较的是对象的地址,-128到127之间两个相同数字是从缓存中拿到的同一个对象,“ == ”自然返回就是true,当不在-128到127之间两个相同数字获取到的是系统new出来的两个新对象,虽然数值相等,但是地址肯定不同,“ == ”返回false也就没啥可大惊小怪的了吧。那如此说来,要判断两个Integer型数字是否相等使用“==”号应该是不规范的,那我们该如何判断两个Integer型数字是否相等呢?正确姿势应该如下:
Integer integera = 1;
Integer integerb = 1;
Integer integerc = 127;
Integer integerd = 127;
Integer integere = 128;
Integer integerf = 128;
//当然前提要有非null判断
System.out.println("integera==integerb:" (integera.equals(integerb)));
//当然前提要有非null判断
System.out.println("integerc==integerd:" (integerc.equals(integerd)));
//当然前提要有非null判断
System.out.println("integere==integerf:" (integere.equals(integerf)));
运行结果:
integera==integerb:true
integerc==integerd:true
integere==integerf:true
那为啥用equals呢,固有印象中equals不是比较字符串大小吗?啥也不说,上源码:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
哦,原来人家的equals方法是先判断参数如果是Integer型,直接取int值进行比较,那这就没啥可说的了吧,至此,同学们是不是对Integer型数字判断是否相等有了新的认识呢?
,