1.看下面的代码,输出什么呢?
Integer n1 = new Integer(127);
Integer n2 = new Integer(127);
System.out.println("n1 == n2:" + (n1 == n2));//false
Integer n3 = 127;
Integer n4 = 127;
System.out.println("n3 == n4:" + (n3 == n4));//true
Integer n5 = new Integer(128);
Integer n6 = new Integer(128);
System.out.println("n5 == n6:" + (n5 == n6));//false
Integer n7 = 128;
Integer n8 = 128;
System.out.println("n7 == n8:" + (n7 == n8));//false
输出结果:
n1 == n2:false
n3 == n4:true
n5 == n6:false
n7 == n8:false
首先我们知道“==”比较的不是对象的值,而是对象的引用。
那么n1==n2 和 n5==n6 返回false,这很好理解,因为都是通过new创建的不同对象。
但是为什么n3==n4返回true,而n7==n8返回false呢?
是这样的:
-128 ~ 127 这些数字会在内存里长期缓存,如果有哪个变量的值是处于这期间的(包含-128和127),都会从这缓存里取,所以取到的是同一个。
总结一下,对于下列包装对象的两个实例,当它们的基本值相同时,他们用==比较总是返回true:
Boolean
Byte
Character, \u0000 - \u007f(7f是十进制的127)
Integer(-128 ~ 127)
Short (-128 ~ 127)
Long (-128 ~ 127)
2.如果想比较两个对象的实际内容是否相同,如何操作呢?
用对象的通用比较方法:equals()方法。
上面的n1~n8任意两个对象之间用equals方法比较,返回的都是true。
3.但是注意,equals()方法不能用于基本类型。比如下面这样是不行的,因为equals()方法是类的方法。
int a = 1;
int b = 1;
System.out.println(a.equals(b)); //编译不通过
4.用equals()来比较对象内容是否相同,是不是适用于所有的类呢?答案是并非适用于所有的类。
看下面的例子:
class Value {
int i;
}
public class CompareMethod{
public static void main(String[] args) {
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.out.println(v1.equals(v2));
}
}
输出为false!是的,为什么和上面第二步的结果不一样呢?
因为Java类的equals()方法默认的行为也是比较引用。参见Java Object类的equals()方法:
public boolean equals(Object obj)
{
return this == obj;
}
而上面用到的Integer类里其实是覆盖了equals()方法的,覆盖后它被用来比较内容。而我们自定义的Value类并没有覆盖equals()方法,用的还是Object类的equals()方法。
(大多数java类库都覆盖了equals方法,用来比较对象内容而非对象的引用。)
所以,要想让我们自定义的类在比较内容时表现出我们想要的样子,就得覆盖equals()方法。
4.下面以String类为例看看效果。String类本身已经重写了equals方法,重写后的equals方法用来比较内容。
如果在一个方法里,定义了如下三个字符串:
String A = "hello";
String B = new String("hello");
String C = new String(A);
那么,下面的输入是什么呢?
System.out.println("A.equals(B):" + A.equals(B));
System.out.println("A.equals(C):" + A.equals(C));
System.out.println("B.equals(C):" + B.equals(C));
System.out.println("A==B:" + (A==B));
System.out.println("A==C:" + (A==C));
System.out.println("B==C:" + (B==C));
首先我们要知道,String类已经重写了equals方法,重写后的equals方法用来比较内容,参见String类源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
因为String类的equals方法比较的是值,所以equals比较当然返回true。而A,B,C是三个不同的对象,所以其地址是不同的,用==比较,返回的是false。
答案:
A.equals(B):true
A.equals(C):true
B.equals(C):true
A==B:false
A==C:false
B==C:false
上面要注意的是:new String(“hello) 和new String(A)有什么区别吗?
这两个传入的都是字符串“hello”,调用的构造方法也是同一个:
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
因此没有什么区别,都会创建一个新的字符串对象。