今天和同事闲聊,聊到了Integer类型判断相等的问题。于是花了点时间整理了一下。
java中每个基本数据类型都有一个对应的包装类。一般我们在操作的时候,(尤其是判断大小的时候),基本都是没有注意包装类和基本类型之间的不同。因为在代码编译的时候,编译器已经对包装类做了拆箱和装箱的处理,所以在表面上给我们一种他们的值是一样的错觉。
这里是实例代码:
public class AA {
public static void main(String[] args) {
Integer c=127;
Integer cc=127;
Integer d=128;
Integer dd=128;
System.out.println((c == cc));//true
System.out.println((d == dd));//false
int c1=127;
int cc1=127;
int d1=128;
int dd1=128;
System.out.println((c1 == cc1));//true
System.out.println((d1 == dd1));//true
Float a=127f;
Float aa=127f;
Float b=128f;
Float bb=128f;
System.out.println((a == aa));//false
System.out.println((b == bb));//false
float a1=127f;
float aa1=127f;
float b1=128f;
float bb1=128f;
System.out.println((a1 == aa1));//true
System.out.println((b1 == bb1));//true
}
}
执行结果如下:
true
false
true
true
false
false
true
true
首先,以Integer为例,
可以看到,当两个数都是127的时候,他们是相等的,但是如果是128就不相等了。这是为什么呢?
public class AA
{
public static void main(String[] args)
{
Integer c = Integer.valueOf(127);
Integer cc = Integer.valueOf(127);
Integer d = Integer.valueOf(128);
Integer dd = Integer.valueOf(128);
System.out.println(c == cc);
System.out.println(d == dd);
int c1 = 127;
int cc1 = 127;
int d1 = 128;
int dd1 = 128;
System.out.println(c1 == cc1);
System.out.println(d1 == dd1);
Float a = Float.valueOf(127.0F);
Float aa = Float.valueOf(127.0F);
Float b = Float.valueOf(128.0F);
Float bb = Float.valueOf(128.0F);
System.out.println(a == aa);
System.out.println(b == bb);
float a1 = 127.0F;
float aa1 = 127.0F;
float b1 = 128.0F;
float bb1 = 128.0F;
System.out.println(a1 == aa1);
System.out.println(b1 == bb1);
}
}
通过查看编译后的class文件,我们可以看到“Integer c=127;”在编译成class文件以后,变成了“Integer c = Integer.valueOf(127);”
接下来我们看看Integer的源码
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
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) -1);
}
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的值在-128和127之间的话,就直接从缓存池里面取这个对象,不管定义多少个Integer变量,其实指向的都是同一个对象。但是超过这个范围以后,就是不同的对象了。(Short,Long同理)
好,那么为什么Float却全是false呢?
我们再来看看Float的valueof()方法的源码
public static Float valueOf(float f) {
return new Float(f);
}