Java中equals()方法实例详解

网友投稿 243 2022-11-12

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;

}

}

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中进行比较,我们需要根据比较的类型来选择合适的比较方式:

对象域,使用equals方法 。

类型安全的枚举,使用equals或== 。

可能为null的对象域 : 使用==null 和 equals 。

数组域 : 使用 Arrays.equals 。

除float和double外的原始数据类型(int,byte等) : 使用 == 。

float类型: 使用Float.foatToIntBits转换成int类型,然后使用==。

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()方法的使用必须要遵循如下几个规则:

自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。

对称性:对于任何非空引用值 x 和 y,当且仅当y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。

传递性:对于任何非空引用值 x、y 和z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。

一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回4、一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回false,前提是对象上 equals 比较中所用的信息没有被修改

对于任何非空引用值 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 (person.getName() == null | name == null) {

return false;

} else {

return name.equalsIgnoreCase(person.getName());

}

}

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) && employee.getId() == id;

}

return false;

}

}

输出:

true

true

false

上述代码中,我定义了一个Person类,有一个属性name;还定义了一个Employee类,它是Person的子类,多出一个id的属性;在测试代码中“new”出了三个对象:

name为mily,id为1的一个职员 —— employee

name为mily,id为2的职员 —— employee2

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() != obj.getClass()){

return false;

}

Person person = (Person) obj;

if(person.getName() == null | name == null) {

return false;

} else {

return name.equalsIgnoreCase(person.getName());

}

}

}

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() != obj.getClass()){

return false;

}

Employee employee = (Employee) obj;

if(employee.getName() == null | getName() == null) {

return false;

}else {

return getName().equalsIgnoreCase(employee.getName()) && employee.getId() == 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);

总结

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Tomcat创建虚拟主机
下一篇:Tomcat的安装和部署
相关文章

 发表评论

暂时没有评论,来抢沙发吧~