首先看下面示例:
Integer i1 = 30;
Integer i2 = 30;
Integer i3 = 300;
Integer i4 = 300;
Integer i5 = -30;
Integer i6 = -30;
System.out.println("i1.equals(i2):"+i1.equals(i2));
System.out.println("i3.equals(i4):"+i3.equals(i4));
System.out.println("i3==i4:"+(i3==i4));
System.out.println("i5==i6:"+(i5==i6));
运行结果:
i1.equals(i2):true 包装类型代码规范来讲,都会建议使用equals进行比较
i3.equals(i4):true
i3==i4:false
i5==i6:true
解释:
Integer是对象,我们发现:如果i1==i2,可以返回true,i3==i4返回false,很奇怪,我们看下Integer的源码
/**
*此⽅法将始终缓存-128 到 127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
默认IntegerCache.low 是-127,Integer.high是128,如果在这个区间内,他就会直接使用常量池中的对象i;但如果不在这个范围内,就会去new一个Integer对象,所以两个对象==地址不同,返回false
然后我们来看两个对象equals为什么返回true,那我们需要分析 == 和 equals的区别:
==是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的,所以i3==i4返回false;
而equals,
首先我们知道Java中Object类是所有类的父类,它里面定义了equals()方法:
public boolean equals(Object obj) {
return (this == obj);
}
可以看到是使用= =来进行比较的,比较两个对象的的内存地址。
Integer 继承并重写了equals方法,拆箱称int,再去比较(而对于基本数据类型(byte,short,char,int,float,double,long,boolean)来说,他们是作为常量在方法区中的常量池里面以HashSet策略存储起来的,在常量池中,一个常量只会对应一个地址,因此基本数据类型和String常量是可以直接通过==来直接比较的。)