1. 基础数据类型
String s4 = new String("abcde");
String s3 = "abcde";
输出的结果仍为:
s3 equals s4: true
s3 == s4: false
因为使用new一定是创建一个新对象s4,此时,不管Constant Pool中是否已经有相同值的对象存在,都会创建一个新的String对象存储在堆中,然后返回其引用给s3。
Java中的基础数据类型
:byte,short,char,int,long,float,double,boolean,使用==进行值的比较,没有equals方法。
2. 复合数据类型
Java中不是基础数据类型的其他类型都是复合数据类型,包括:class、interface、数组、String。所有类都是从Object中衍生而来,在Object类中定义的equals方法源码为:
public boolean equals(Object obj) {
return (this == obj);
}
可见,未覆盖的equals方法是由==实现的,而对于复合数据类型,== 比较的是两个对象的内存地址,除非两个对象指向的是同一个内存地址的引用,才可能相同。调用未重写的equals方法是没意义的,其结果与==的结果一致。
例如:
class Words {
String value;Words(String str) {value = str;}
}
Words s6 = new Words("abcde");
Words s7 = new Words("abcde");
Words s8 = s7;
System.out.println("s7 equals s6: " + s7.equals(s6));
System.out.println("s7 == s6: " + (s7 == s6 ));
System.out.println("s8 equals s7: " + s8.equals(s7));
System.out.println("s8 == s7: " + (s8 == s7 ));
输出结果为:
s7 equals s6: false
s7 == s6: false
s8 equals s7: true
s8 == s7: true
我们可以重写equals方法,例如在String类中重写的equals方法源码为:
public boolean equals(Object anObject) {
if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = count;if (n == anotherString.count) {char v1[] = value;char v2[] = anotherString.value;int i = offset;int j = anotherString.offset;while (n-- != 0) {if (v1[i++] != v2[j++])return false;}return true;}}return false;
}
可见,equals先比较两个对象的内存地址,若指向同一个内存地址,则返回true;
若内存地址不同,equals再比较的是两个String对象的内容,即长度与每个字符的值,相同则返回true。
所以:
String s4 = new String("abcde");
String s5 = new String("abcde");
String s9 = s5;
System.out.println("s5 equals s4: " + s5.equals(s4));
System.out.println("s5 == s4: " + (s5 == s4 ));
System.out.println("s5 equals s9: " + s5.equals(s9));
System.out.println("s5 == s9: " + (s5 == s9 ));
输出结果为:
s5 equals s4: true
s5 == s4: false
s5 equals s9: true
s5 == s9: true
我们知道String的equals方法进行了重写的,但是,对于下面的代码:
String s1 = "abc";
String s2 = "abc";
System.out.println("s1 equals s2:" + s1.equals(s2));
System.out.println("s1 == s2: " + (s1 == s2));
输出结果为:
s1 equals s2:true
s1 == s2: true
可以看出,s1==s2的结果与上面s4==s5的结果不同。原因在于,创建s4,s5时使用的是new,会在内存中各开辟一块空间存放s4,s5对象,所以二者的内存地址不同,s5 == s4的结果为 false;而创建s1,s2时,二者引用的是同一个String对象,所以 s1 == s2的结果为true。
类似地,如果:
String s3 = "abcde";
String s4 = new String("abcde");
System.out.println("s3 equals s4: " + (s3.equals(s4)));
System.out.println("s3 == s4: " + (s3 == s4 ));
输出结果为:
如果交换s3,s4的位置:s3 equals s4: trues3 == s4: false
String s4 = new String("abcde");
String s3 = "abcde";
输出的结果仍为:
s3 equals s4: true
s3 == s4: false
因为使用new一定是创建一个新对象s4,此时,不管Constant Pool中是否已经有相同值的对象存在,都会创建一个新的String对象存储在堆中,然后返回其引用给s3。
Constant Pool是Java编译好的class文件中的一个区域,是一个由数组组成的表,用来存储程序中使用的各种常量,包括Class、String、Integer等类型。
总结:
当用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。
Java当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是使用(==)比较对象的内存地址,比较后的结果跟双等号(==)的结果相同。但在一些类当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,可能不再是比较类在内存中的存放地址了。
参考:
Java中equals和==的区别
http://www.cnblogs.com/zhxhdean/archive/2011/03/25/1995431.html