Java中equals()⽅法实例详解
⽬录
equals()在哪⾥
Java中重写的equals()
在Java中⽐较的推荐⽅法
为什么要在我们⾃⼰的类中重写equals()
重写equals()的规范
重写equals()可能的误区
⼀般的equals()写法
附:java中equals()⽅法的正确使⽤
总结
equals()在哪⾥
⾸先我们知道Java中Object类是所有类的⽗类,它⾥⾯定义了equals()⽅法:
public boolean equals(Object obj) {
return (this == obj);
}
可以看到是使⽤= =来进⾏⽐较的,那么= =是什么意思呢?其实是⽐较两个对象的的内存地址。(这⾥顺便提⼀下,可以去了解⼀下Java的堆栈。)
=》若object1.equals(object2)为true,则表⽰equals1和equals2实际上是引⽤同⼀个对象。
Java中重写的equals()
这⾥我们看⼀下java的⼀些⾃带的包装类怎么重写equals()的:
String.java
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;
}
}
equals()方法return false;
}
我们可以⾮常清晰的看到String的equals()⽅法是进⾏内容⽐较,⽽不是单纯的引⽤⽐较。
Integer.java
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
其他的就不⼀⼀举例了。
在Java中⽐较的推荐⽅法
所以我们⼀般⽐较基本数据类型的时候,使⽤"==",例如 int i = 0; if (i == 1){…},⽐较两个Integer包装类类型的时候就可以使⽤equals(),因为Java已经重写了equals()⽅法了。另外给出⼏点建议,在java中进⾏⽐较,我们需要根据⽐较的类型来选择合适的⽐较⽅式:
1. 对象域,使⽤equals⽅法。
2. 类型安全的枚举,使⽤equals或== 。
3. 可能为null的对象域 : 使⽤==null 和 equals 。
4. 数组域 : 使⽤ Arrays.equals 。
5. 除float和double外的原始数据类型(int,byte等) : 使⽤ == 。
6. float类型: 使⽤Float.foatToIntBits转换成int类型,然后使⽤==。
7. double类型: 使⽤Double.doubleToLongBit转换成long类型,然后使⽤==。
其中6,7参考java中的对应的包装类实现:
public boolean equals(Object obj) {
return (obj instanceof Float)
&& (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}
}
为什么要在我们⾃⼰的类中重写equals()
但是有时候我们不满⾜于使⽤基本数据类型和Java实现的⼀些继承⾃Object的哪些类,⽐如我们实现⼀个Person类,它是继承⾃Object类的,所以它的equals()⽅法默认使⽤的是⽂章开头提到的哪个equals()⽅法,当我们使⽤equals()进⾏⽐较的时候,⽐较内存地址,那么有可能出现两个Person对象的参数都相同(⽐如年龄,⾝份证号等,在我们的实际认知中认为这两个⼈就是⼀个⼈,应该返回true),但是由于他们的内存地址是不⼀样的,所以equals()⽅法会返回false。
那么我们就需要去重写equals()⽅法。
重写equals()的规范
需要注意的是,在Java规范中,它对equals()⽅法的使⽤必须要遵循如下⼏个规则:
1. ⾃反性:对于任何⾮空引⽤值 x,x.equals(x) 都应返回 true。
2. 对称性:对于任何⾮空引⽤值 x 和 y,当且仅当y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
3. 传递性:对于任何⾮空引⽤值 x、y 和z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返
回 true。
4. ⼀致性:对于任何⾮空引⽤值 x 和 y,多次调⽤ x.equals(y) 始终返回 true 或始终返回4、⼀致性:对于任何⾮空引⽤值
x 和 y,多次调⽤ x.equals(y) 始终返回 true 或始终返回false,前提是对象上 equals ⽐较中所⽤的信息没有被修改
5. 对于任何⾮空引⽤值 x,x.equals(null) 都应返回false。
重写equals()可能的误区
查看下述代码:
public class TestEquals {
public static void main(String[] args) {
Employee employee = new Employee("mily",1);
Employee employee2 = new Employee("mily",2);
Person p1 = new Person("mily");
System.out.println(p1.equals(employee));
System.out.println(p1.equals(employee2));
System.out.println(employee.equals(employee2));
}
}
class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person person = (Person) obj;
if (Name() == null | name == null) {
return false;
} else {
return name.Name());
}
}
return false;
}
}
class Employee extends Person {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Employee(String name, int id) {
super(name);
this.id = id;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Employee) {
Employee employee = (Employee) obj;
return super.equals(obj) && Id() == id;
}
return false;
}
}
输出:
true
true
false
上述代码中,我定义了⼀个Person类,有⼀个属性name;还定义了⼀个Employee类,它是Person的⼦类,多出⼀个id的属性;在测试代码中“new”出了三个对象:
1. name为mily,id为1的⼀个职员 —— employee
2. name为mily,id为2的职员 —— employee2
3. name为mily的⼀个普通⼈ —— p1
在⼤家的认知下,应该是三者都不是“equal”的,但是在执⾏ p1.equals(employee)时返回的是true,仔细看了代码之后你就会发现问题所在,代码把employee当成⼀个Person对象去执⾏equals⽅法了,⽐较了name发现⼀样,就认为是“equal”了,这是⼀种很常见的误区。
⼀般的equals()写法
下⾯给出⼀个完美的 equals ⽅法的建议:
1、显⽰参数命名为 otherObject,稍后会将它转换成另⼀个叫做 other 的变量。
2、判断⽐较的两个对象引⽤是否相等,如果引⽤相等那么表⽰是同⼀个对象,那么当然相等
3、如果 otherObject 为 null,直接返回false,表⽰不相等
4、⽐较 this 和 otherObject 是否是同⼀个类:如果 equals 的语义在每个⼦类中有所改变,就使⽤ getClass 检测;如果所有的⼦类都有统⼀的定义,那么使⽤ instanceof 检测
5、将 otherObject 转换成对应的类类型变量
6、最后对对象的属性进⾏⽐较。使⽤ == ⽐较基本类型,使⽤ equals ⽐较对象。如果都相等则返回true,否则返回false。注意如果是在⼦类中定义equals,则要包含 super.equals(other)
按照上述的equals()规范,我的实现如下:
public class TestEquals2 {
public static void main(String[] args) {
Employee employee = new Employee("mily",1);
Employee employee2 = new Employee("mily",1);
Person p1 = new Person("mily");
System.out.println(p1.equals(employee));
System.out.println(p1.equals(employee2));
System.out.println(employee.equals(employee2));
Employee employee3 = new Employee(null,1);
Employee employee4 = new Employee(null,1);
Person p2 = new Person(null);
System.out.println(p2.equals(employee3));
System.out.println(p2.equals(employee4));
System.out.println(employee3.equals(employee4));
}
}
class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null || getClass() != Class()){
return false;
}
Person person = (Person) obj;
Name() == null | name == null) {
return false;
} else {
return name.Name());
}
}
}
class Employee extends Person {
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Employee(String name, int id) {
super(name);
this.id = id;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj == null || getClass() != Class()){
return false;
}
Employee employee = (Employee) obj;
Name() == null | getName() == null) {
return false;
}else {
return getName().Name()) && Id() == id;
}
}
}
结果:
false
false
true
false
false
false
附:java中equals()⽅法的正确使⽤
在Java中⽐较两个字符串是否相等,想必只要不是初学者都知道⽤equals()⽅法来进⾏⽐较,但是实际上很多时候都⽤错了。
就我⾃⼰开发⽽⾔,加⼊⽐较⼀个String s的内容是否是"aaa"时,往往会写成如下代码:
if(s.equals("aaa")){
...
}
乍⼀看没什么问题,直到我装了Alibaba Coding Guidelines 这个插件,⼀检查,就告诉我这样不对了。
为什么呢?因为很多情况下,并不能保证字符串s是不是为null,即直接这么判断,很容易产⽣空指针异常的错误,因此正确的使⽤⽅法应该是:
"aaa".equals(s);
总结
到此这篇关于Java中equals()⽅法的⽂章就介绍到这了,更多相关Java equals()⽅法内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论