新定义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());
}
}

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

被折叠的 条评论
为什么被折叠?



