equals()和“==”的用法与区别
首先来看equals方法的源码:
public boolean equals(Object obj){
return this(Object==obj);
}
从源码可以看出equals和“==”运算符一样比较的是两个对象的引用(地址值)是否一样。equals方法和toString方法一样都是Object超类的方法。对于Object对象,equals方法比较得是对象的地址是否一样,但为什么我们常见的equals方法大部分在比较对象的内容是否一样呢?这是因为有些方法重写了equals方法,使其不再比较得是对象的地址值而是对象的内容。常见重写了equals方法的有String、Math等封装类都对equals方法进行了重写。
当然equals方法和“==”的用法主要分为以下几种情况:
1、用在String字符串的对象的比较
来看一段代码:
public class fun1{
public void test(){
String s1,s2="abc"m,s3="abc";
String s1=new String("abc");
String s2=new string("abc");
System.out.println(s1==s2);
System.out.println(s2==s3);
System.out.println(s1.equals(s2));
}
}
对于第2个比较s2==s3首先比较得是s2和s3的地址值是否一样,由于他们都是字符串常量对象,所以引用是一样的,即属于同一对象,即答案为:true。而对于s1和s2由于他们是2个不同的对象,所以地址值不同,答案为false。
对于第三个,由于String类重写了equals方法,equals比较得是对象的内容是否一样,所以答案是true。
2.特殊情况
StringBuffer res1=new StringBuffer("a");
StringBuffer res2=new StringBuffer("a");
System.ou.println(res1==res2);
System.ou.println(res1.equasls(res2));
答案都是false。这是因为对于第一个比较而言,由于都用的是new关键字创建对象,所以res1和res2是2个不同的对象,即在内存中的地址也不一样,所以答案为false。对于第二个答案为false是因为:在StringBuffer中没有重新equals方法,所以equals方法此时和“”==”一样比较得是对象的地址值是否相同。(其实此时运用new关键字创建对象时在内存中创建了2个对象,一个在常量池中(对象“a”),一个在堆中(对象s1,s2))。这是一种特别情况需要特别注意。
3.基本数据类型对象的比较
如果两个对象的数据类型为八个基本的数据类型(byte、short、int、double、long、float、char、boolean),对于对象间的比较只能用“==”运算符。
来看一段代码:
public class fun2{
public void test2(){
double a=1.0;
double b=2.0;
double c=1.0;
System.out.println(a==b);//false
System.out.println(a==c);//true
System.out.println(a.equals(c));//报错
}
}
对于两个比较得都是地址是否相同,a和b是两个不同的对象,所以引用地址不同,答案为false,对于a和c表示的是常量,都在其实是同一对象保存在常量池中,所以答案为true。而对于a.equals(c)来说,因为对象的数据类型为基本数据类型,所以不能使用equals方法比较这两个对象,否则会报:Cannot invoke equals(double) on the primitive type double错误。
4.基本数据类型的包装类对象的比较
对于八大基本数据类型(byte、short、int、double、long、float、char、boolean)的/包装类(Byte、Short、Integer、Double、Long、Float、Character、Boolen)对象间的比较而言,“==”比较的是对象的地址值,equals比较的是对象的内容。
public class fun3{
public void test3(){
Integer a=11;
Integer b=21;
Integerc=11;
System.out.println(a==b);//false
System.out.println(a==c);//true
System.out.println(a.equals(c));//true
}
}
5.非字符串变量对象的比较
对于非字符串对象的比较,equals方法和“==”一样比较的是对象在堆中的首地址是否相同,即两个对象的引用是否指向同一对象。
public class fun4{
public void test4(){
//do Something
}
}
//测试类:
public class A{
public static void main(String[]args){
fun4 a=new fun4();
fun4 b=new fun4();
System.ou.println(a==b);//false
System.ou.println(a.equals(b));//false
//test4();
}
}
这里a,b是两个不同的对象,所以他们在堆中的地址不同,而equals和“==”一样比较的对象的引用地址是否相同,所以答案为false。
6.总结:
总之对于equals和“==”而言本身是对对象的引用进行比较。然而由于String、Math等包装类(包括基本数据类型的包装类Byte、Short、Integer、Double、Long、Float、Character、Boolen)对equals方法进行了重写,所以对于常见的字符串对象equals比较的是内容是否相同,需要特别注意的是StringBuffer没有重写equals方法,所以“==”和equals一样比较的是对象在堆中的引用是否相同。对于“==”需要注意是在八大基本数据类型对象的比较时,只能用“==”’,不能用equals比较。
推荐阅读