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; }因此没有什么区别,都会创建一个新的字符串对象。