equals方法详解

  • Java中所有的类都继承了Object超类,因此每个对象都有equals()方法
/**源码:Object类中的equals()方法,不重写equals方法则默认继承以下方法
 */
public boolean equals(Object obj) {
        return (this == obj);
    }
  •     Object类中的equals方法用于检测一个对象是否等于另外一个对象。Object类中实现的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 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。 
    5、对于任何非空引用值 x,x.equals(null) 都应返回 false。

  • 代码示例一

1、创建实体类Student.java

public class Student {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
 public Student(String name) {
        this.name = name;
    }
}

2、创建测试类Test1.java

public class Test1 {
 
    public static void main(String[] args) {
        Student stu1=new Student("小明");
        Student stu2=new Student("小明");
        System.out.println(stu1.equals(stu2));
    }
}

 

3、运行结果为false

因为上面测试类中的equals方法默认的是继承的Object中的,该默认方法只是比较两个对象引用是否相同,因为创建的是两个对象,所以比较结果是false即使里面的数据是相同的。

  • 代码示例二

1、创建Student.java并重写equals和hashCode方法

public class Student {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**此处为重写Object中默认equals方法,显然默认的equals方法是不满足我们的比较条件的,需要对
     * 原有方法进行完善,第一个if是比较的两个对象引用是否相同,第二个if为比较两个对象中的数据
     * 是否相同,显然两个对象的引用是不同的。但是在给name赋值相同的情况下,满足第二个if条件
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        if (obj==this){
            return true;
        }
        if(obj instanceof  Student){
            Student sutdent=(Student) obj;
            if(sutdent.getName().equals(this.name)){

                return true;
            }
        }
        return false;
    }

    /**当你重写了equals方法之后必须要重写hashCode方法,否则hashCode方法还是原来的
     * 重写hashCode方法
     * @return
     */

    @Override
    public int hashCode() {
        return this.name.hashCode();
    }

    public Student(String name) {
        this.name = name;
    }
}

ps:注意上面类中重写hashCode方法部分,散列码(hash code)是由对象导出的一个整型值,可以是负数。散列码是没有规律的。由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值由对象的存储地址得出。如果重新定义了equals方法,就必须为用户可能插入散列表的对象重新定义hashCode方法

  • hashcode的作用

利用HashSet/HashMap/Hashtable类来存储数据时,为了提高程序的效率,先进行hashcode的比较,如果不同,那没就不必在进行equals的比较了,这样大大减少了equals比较的次数,从而大幅度提高了效率。

JDK的API建议:equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。常规协定如下 
(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()必须为true 
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj1.equals(obj2)必须为false

上面的例子中,我们重写了equals方法,并规定只要对象的name属性值相同,两个对象就相等,很显然我们的目的可以轻松达到。但是我们没有重写hashCode方法,hashCode方法仍然返回原对象的内存地址,所以两个对象的hashCode值还是不相等,这就违反了hashCode 方法的常规协定。后果是,在某些利用对象hashCode值做索引的情况下,这样会造成混乱,相当于没有重写equals方法。

2、创建Test2.java

public class Test1 {
    /**
     * 用于测试重写equals方法之后,两个对象在值相同的情况下的比较结果。
     * 下面代码返回值为true因为在Student类中重写了equals方法,如果用默
     * 认的equals方法会返回false。
     * @param args
     */
    public static void main(String[] args) {
        Student stu1=new Student("小明");
        Student stu2=new Student("小明");
        System.out.println(stu1.equals(stu2));
    }
}

 3、运行结果:true。因为在Student.java类中对equals方法进行了重写,仔细看Student类中重写的equals方法

PS:开发中容易报错的地方,在进行a.equals(b)的时候,如果a为null这个时候代码就会报空指针的异常,因此要将明确的常量值放在前面,这样如果b为null时,执行结果为false,但是不会报空指针异常。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪头的彩虹糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值