代码1:
public static void main(String[] args) {
int a = 10;
int b = 10;
Integer c = 10;
Integer d = 10;
Integer e = 128;
Integer f = 128;
System.out.println(a == b);
System.out.println(c == d);
System.out.println(e == f);
}
结果:
代码2:
public static void main(String[] args) {
Integer a = new Integer(10);
Integer b = new Integer(10);
System.out.println(a.equals(b));
}
结果:
代码3:
public class BiJiaoTest {
public static void main(String[] args) {
Value a = new Value();
Value b = new Value();
a.i = b.i = 10;
System.out.println(a == b);
}
}
class Value{
int i;
}
结果:
代码4:
public class BiJiaoTest {
public static void main(String[] args) {
Value a = new Value();
Value b = new Value();
a.i = b.i = 10;
System.out.println(a.equals(b));
}
}
class Value{
int i;
}
结果:
总结:
== 是一个关系运算符,使用与所有内建的数据类型,同样也适用于所有对象,检查两个对象是否相等。
代码1中,a == b 返回true。因为a 、b 都是基本数据类型,基本数据类型都是存在栈里面的,当jvm执行int a = 10时,首先会创建 int a 的引用,然后去栈里面找是不是有一个数据为10,如果有就将a 指向这个地址,如果没有就创建一个地址。int b = 10也是相同的道理。所以当a 和 b 值相同的时候,地址也是相同的。
代码1中,c == d 返回true。Integer c = 10 是int 类型的自动装箱操作,调用了Integer的valueOf()方法,当c >= -128 并且c <=127时,用了常量池技术,所以c 和 d的地址也是相同的。valueOf源码如下:
public static Integer valueOf(int i) {
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) {
try {
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);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
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() {}
}
代码1中,e == f 返回false。因为e 和 f 大于127 ,进行了new 的操作,e 和 f 的地址是不同的。
equals()方法是Object类中的一个方法,方法中也是用 “==” 来实现的。下面是Object类中equals()方法的源码:
public boolean equals(Object obj) {
return (this == obj);
}
所以equals()方法比较的也是两个对象的地址。但是为什么代码2中用equals()方法结果却是true呢?因为Integer类中重写了equals()方法,方法中把Integer进行拆箱操作,对比的是基本数据类型。源码如下:
private final int value;
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
代码4中Value对象并没有重写父类Object的equals()方法,所以调用的其实是Object类中的equals()方法,其实也是用==比较的 所以结果为false;
- ==永远是用来比较内存中的地址的,基本类型感觉上是在比较内容,实际上还是在比较地址!
- 大多数JAVA类库都重了写equals()方法,所以它实际比较的是对象的内容,而非他们的地址。
- 但是在我们自定义的对象中,如果我们没有重写equals()方法,那么他们比较的就是地址而非内容。
- 重写equals()方法应注意以下几点:
- 自反性:对任意引用值x,x.equals(x)的返回值一定为true;
- 对称性:对于任意引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
- 传递性:如果x.equals(y) = true,y.equals(z) = true,则x.equals(z) = true;
- 一致性:如果参与比较的对象没有任何改变,则对象比较的结果也不应该有任何改变。
- 非空性:任何非空的引用值x,x.equals(null)的返回值一定为false。