新定义类重写equals、hashCode方法

本文介绍了如何在Java中定义一个Student类,并对其成员变量name和id进行封装。接着,讨论了默认equals方法的行为,并展示了如何根据成员变量重写equals方法以满足特定的比较逻辑。同时,解释了equals和hashCode方法之间的关系,并重写了hashCode方法以确保等价对象具有相同的哈希码。最后,通过测试代码验证了重写后的equals和hashCode方法的效果。

新定义Student类

定义Student类,新建成员变量name,id并进行封装

public class Student {
    private String name;
    private int id;

    public Student() {
    }

    public Student(String name, int id) {
        setName(name);
        setId(id);
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        if(id>0)
            this.id = id;
        else
            System.out.println("illegal id!");
    }
}

对Student继承的equals方法进行测试

public class StuTest {
    public static void main(String[] args) {
        Student s1=new Student("zhangsan",100);
        Student s2=new Student("wangwu",200);
        Student s3=new Student("zhangsan",100);
        //引用类型变量存储的是栈区地址,s1、s2地址显然不同
        System.out.println("s1==s2:"+(s1==s2)); //false
        ///使用equals方法测试
        System.out.println("s1.equals(s2):"+s1.equals(s2));
        System.out.println("s1.equals(s3):"+s1.equals(s3));
    }
}

运行结果如下
在这里插入图片描述
由于Student类没有重写equals方法,其equals方法为继承自Object类的方法,查看Object的equals方法
在这里插入图片描述
对于Object的equals方法,当比较对象是引用变量时,仅当比较的两个变量指向同一个对象时返回true,也就是存储的地址相同时为true;

重写equals方法

下面希望通过成员变量name和id来区分一个学生,当s1和s3的name、id都相同时,将他们认为是同一个学生,即s1.equals(s3)=true。
在Student类中重写equals方法时,需要比较两个字符串name是否相同,而String是引用数据类型,简单的s1.getName()==s3.getName()只能比较name变量中的地址,显然不可行。参阅api文档可发现String类型对equals方法进行了重写,如下:
在这里插入图片描述
因此在次处使用equals方法即可。此外,重写Student类的equals方法时,还需要考虑传入引用变量是否为空,是否为Student类型和本身的字符串是否为空。重写如下:

@Override
    public boolean equals(Object obj) {
        //判断是否为空,是否是Student类型,this本身不可能为空,否则引发空指针异常
        if(obj==null||obj.getClass()!=Student.class)return false;
        //自反性,传入自身
        if(obj==this)return true;
        //强制类型转换
        Student student=(Student)(obj);
        //判断id是否相同
        if(getId()!=student.getId())return false;
        //在判断字符串name是否相同,而name可能为空
        return name!=null?getName().equals(student.getName()):student.getName()==null;
    }

再次执行测试代码后,name和id相同的s1和s3返回了true。
在这里插入图片描述

重写hashCode方法

在查看Object类的equals方法时,可以发现与hashCode相关的内容
在这里插入图片描述
即由于常规协定,通过equals方法返回true的两个对象,其通过hashCode()方法返回的哈希码值也要相同,下面对Student类中的hashCode方法进行重写。

@Override
    public int hashCode() {
        //name为空则为0,否则返回name的哈希码值
        int result=name!=null?name.hashCode():0;
        result=result*31+id;//31是任取的
        return result;
    }

对s1,s3哈希码值进行比较

public class StuTest {
    public static void main(String[] args) {
        Student s1=new Student("zhangsan",100);
        Student s3=new Student("zhangsan",100);
        
        System.out.println("s1.hashCode:"+s1.hashCode());
        System.out.println("s3.hashCode:"+s3.hashCode());
    }
}

在这里插入图片描述
结果相同。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值