Java中判断对象是否相等的equals()方法使用教程
与==运算符响应,equals()方法也是Java中对对象进行比较的一大方式,要特别注意二者的不同点,这个我们在下文中即将讲到,接下来我们就来看一下Java中判断对象是否相等的equals()方法使用教程
Object类中的equals方法用于检测一个对象是否等于另一个对象。在Object类中,这个方法判断两个对象是否具有相同的引用,如果两个对象具有相同的引用,它们一定是相等的。从这点上看,将其作为默认操作也是合乎情理的。然而,对于多数类类说,这种判断并没有什么意义,例如,采用这种方式比较两个PrintStream是否相等就完全没有意义。然而,经常需要检测两个对象状态的相等性,如果两个对象的状态相等,就认为这两个对象是相等的。所以一般在自定义类中都要重写equals比较。
下面给出编写一个完美equals()方法的建议:
(1)显式参数命名为otherObject,稍后需要将转换成一个叫other的变量
(2)检测this与otherObject是否引用同一个对象:
1 if(this==otherObject)returntrue; 这条语句只是一个优化。实际上,这是一种经常采用的形式。因为计算这个等式要比一个一个地比较类中的域所付出的代价小的多。
(3)检测otherObject是否为null,如果为null,返回false。这项检测是很必要的。
1 if(otherObject==null)returnfalse; (4)比较this和otherObject是否属于同一个类,如果equals的语义在每个子类中有所改变,就使用getClass()检测,它将自己作为目标类
1 if(getClass()!=otherObject.getClass())returnfalse; 如果所有的子类都拥有同一的语义,就使用instanceof检测
1 if(!(otherObjectinstanceofClassName))returnfalse; (5)将otherObject转换为相应类型的变量:
1 ClassNameother=(ClassName)otherObject; (6)现在开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域。如果所有域都匹配,就返回true,否则返回false;
1 returnfield1==other.field1&&field2.equals(other.field2) 如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。如果检测失败,就不可能相等。如果超类中的域相等,就比较子类中的实例域。
对于数组类型的域,可以使用静态的Arrays.equals方法检测相应的元素是否相等。
来看几个字符串比较例子:
1
2
3
4
5
6
7
8
9 Stringa="abc";
Stringb="abc";
Stringc=newString("abc");
Stringd=newString("abc");
System.out.println(a==b);//true因为JAVA中字符串常量是共享的,只有一个拷贝
System.out.println(a==c);//falsea和c属于2个不同的对象
System.out.println(a.equals(c));//true由于String对象的equals方法比较的是对象中的值,所以返回true。(和Object的equals方法不同)
System.out.println(c==d);//falsec和d虽然对象内的值相同,但属于2个不同的对象,所以不相等
System.out.println(c.equals(d));//true 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 packagechapter05.EqualsTest;
importjava.util.;
publicclassEqualsTest{
publicstaticvoidmain(String[]args){
Employeealice1=newEmployee("AliceAdams",75000,1987,12,15);
Employeealice2=alice1;//referencethesameobject
Employeealice3=newEmployee("AliceAdams",75000,1987,12,15);
Employeebob=newEmployee("BobBrandson",50000,1989,10,1);
System.out.println("alice1==alice2:"+(alice1==alice2));
System.out.println("alice1==alice3:"+(alice1==alice3));
System.out.println("alice1.equals(alice3):"+(alice1.equals(alice3)));
System.out.println("alice1.equals(bob):"+(alice1.equals(bob)));
System.out.println(bob.toString());
}
}
classEmployee{
publicEmployee(Stringn,doubles,intyear,intmonth,intday){
name=n;
salary=s;
GregorianCalendarcalendar=newGregorianCalendar(year,month,day);
hireDay=calendar.getTime();
}
publicStringgetName(){
returnname;
}
publicdoublegetSalary(){
returnsalary;
}
publicDategetHireDay(){
returnhireDay;
}
publicvoidraiseSalary(doublebyPercent){
doubleraise=salarybyPercent/100;
salary+=raise;
}
@Override
publicbooleanequals(ObjectotherObject){
//aquicktesttoseeiftheobjectsareidentical
if(this==otherObject)
returntrue;
//mustreturnfalseiftheexplicitparameterisnull
if(otherObject==null)
returnfalse;
//iftheclasseddon''tmatch,theycan''tbeequal
if(getClass()!=otherObject.getClass())
returnfalse;
//nowweknowotherObjectisawww.hunanwang.netyee
Employeeother=(Employee)otherObject;
//testwhetherthefieldshavaidenticalvalues
returnname.equals(other.name)&&salary==other.salary
&&hireDay.equals(other.hireDay);
}
@Override
publicinthashCode(){
return7name.hashCode()+11newDouble(salary).hashCode()+13
hireDay.hashCode();
}
@Override
publicStringtoString(){
returngetClass().getName()+"[name="+name+",salary="+salary
+",hireDay="+hireDay+"]";
}
privateStringname;
privatedoublesalary;
privateDatehireDay;
}
classManagerextendsEmployee{
publicManager(Stringn,doubles,intyear,intmonth,intday){
super(n,s,year,month,day);
bouns=0;
}
@Override
publicdoublegetSalary(){
doublebaseSalary=super.getSalary();
returnbaseSalary+bouns;
}
publicvoidsetBouns(doubleb){
bouns=b;
}
@Override
publicbooleanequals(ObjectotherObject){
if(!super.equals(otherObject))
returnfalse;
Managerother=(Manager)otherObject;
//superequalscheckedthatthisandotherbelongtothesameclass
returnbouns==other.bouns;
}
@Override
publicinthashCode(){
returnsuper.hashCode()+17newDouble(bouns).hashCode();
}
@Override
publicStringtoString(){
returnsuper.toString()+"[bouns="+bouns+"]";
}
privatedoublebouns;
} 深入下面根据“类是否覆盖equals()方法”,将它分为2类。(1)若某个类没有覆盖equals()方法,当它的通过equals()比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象。(2)我们可以覆盖类的equals()方法,来让equals()通过其它方式比较两个对象是否相等。通常的做法是:若两个对象的内容相等,则equals()方法返回true;否则,返回fasle。下面,举例对上面的2种情况进行说明。1.“没有覆盖equals()方法”的情况代码如下(EqualsTest1.java):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 importjava.util.;
importjava.lang.Comparable;
/
@descequals()的测试程序。
/
publicclassEqualsTest1{
publicstain(String[]args){
//新建2个相同内容的Person对象,
//再用equals比较它们是否相等
Personp1=newPerson("eee",100);
Personp2=newPerson("eee",100);
System.out.printf("%s\n",p1.equals(p2));
}
/
@descPerson类。
/
privatestaticclassPerson{
intage;
Stringname;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringtoString(){
returnname+"-"+age;
}
}
} 运行结果:
复制代码代码如下:
false
结果分析我们通过p1.equals(p2)来“比较p1和p2是否相等时”。实际上,调用的Object.java的equals()方法,即调用的(p1==p2)。它是比较“p1和p2是否是同一个对象”。而由p1和p2的定义可知,它们虽然内容相同;但它们是两个不同的对象!因此,返回结果是false。
2."覆盖equals()方法"的情况我们修改上面的EqualsTest1.java:覆盖equals()方法。代码如下(EqualsTest2.java):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 importjava.util.;
importjava.lang.Comparable;
/
@descequals()的测试程序。
/
publicclassEqualsTest2{
publicstaticvoidmain(String[]args){
//新建2个相同内容的Person对象,
//再用equals比较它们是否相等
Personp1=newPerson("eee",100);
Personp2=newPerson("eee",100);
System.out.printf("%s\n",p1.equals(p2));
}
/
@descPerson类。
/
privatestaticclassPerson{
intage;
Stringname;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringtoString(){
returnname+"-"+age;
}
/
@desc覆盖equals方法
/
@Override
publicbooleanequals(Objectobj){
if(obj==null){
returnfalse;
}
//如果是同一个对象返回true,反之返回false
if(this==obj){
returntrue;
}
//判断是否类型相同
if(this.getClass()!=obj.getClass()){
returnfalse;
}
Personperson=(Person)obj;
returnname.equals(person.name)&&age==person.age;
}
}
} 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 importjava.util.;
importjava.lang.Comparable;
/
@descequals()的测试程序。
/
publicclassEqualsTest3{
publicstaticvoidmain(String[]args){
//新建2个相同内容的Person对象,
//再用equals比较它们是否相等
Personp1=newPerson("eee",100);
Personp2=newPerson("eee",100);
System.out.printf("p1.equals(p2):%s\n",p1.equals(p2));
System.out.printf("p1==p2:%s\n",p1==p2);
}
/
@descPerson类。
/
privatestaticclassPerson{
intage;
Stringname;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringtoString(){
returnname+"-"+age;
}
/
@desc覆盖equals方法
/
@Override
publicbooleanequals(Objectobj){
if(obj==null){
returnfalse;
}
//如果是同一个对象返回true,反之返回false
if(this==obj){
returntrue;
}
//判断是否类型相同
if(this.getClass()!=obj.getClass()){
returnfalse;
}
Personperson=(Person)obj;
returnname.equals(person.name)&&age==person.age;
}
}
} 运行结果:
1
2 p1.equals(p2):true
p1==p2:false 结果分析:在EqualsTest3.java中:(1)p1.equals(p2)这是判断p1和p2的内容是否相等。因为Person覆盖equals()方法,而这个equals()是用来判断p1和p2的内容是否相等,恰恰p1和p2的内容又相等;因此,返回true。(2)p1==p2这是判断p1和p2是否是同一个对象。由于它们是各自新建的两个Person对象;因此,返回false。
|
|