天天看点

重写equals()&hashCode()&toString()—Java类设计

很多时候,设计一个类,我们需要重写超类Object中的equals(Object o)、hashCode()以及toString()
  • equals(Object o):比较当前对象与指定对象o的状态(比较两个对象中所有字段的值)是否相同,是即返回true,否则返回false
  • hashCode():获得当前对象的散列码,超类Object中定义的hashCode()会将对象的存储地址作为散列码返回
  • toString():为方便操作而存在,可用于打印对象的状态信息
那么,它们三儿具体应该怎么搞呢?

一、User类

定义一个用于测试的类User,包含两个字段以及对应的get/set方法
- age:用户年龄,int类型
- name:用户名字,String类型
class User{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
           

二、重写equals(Object o)

设计步骤:
1. 用“==”判断对象o与当前对象是否为同一个对象,若是则直接返回true
2. 若对象o为null,则直接返回false
3. 根据情况选择使用getClass()方法或instanceOf关键字来判断对象o与当前对象是否为同一类型,若不是则返回false
4. 使用强制类型转换将对象o转化为当前对象类型
5. 依次判断对象o与当前对象中的所有对应字段是否相同,若全部相同则返回true
代码:
class User{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@override
	public boolean equals(Object o) {
		if(this==o)return true;//1、用“==”判断对象o与当前对象是否为同一个对象,若是则直接返回true
		if(o==null)return false;//2、 若对象o为null,则直接返回false
		if(!(getClass()==o.getClass()))return false;//3、使用getClass()方法来判断对象o与当前对象是否为同一类型,若不是则返回false
		User user=(User)o;//4、使用强制类型转换将对象o转化为当前对象类型User
		return user.getAge()==age&&Objects.equals(name,user.getName());//5、依次判断对象o与当前对象中的所有对应字段是否相同,若全部相同则返回true
	}
}
           

三、重写hashCode()

设计步骤:
1. 只要重写了equals()方法,则必须重写hashCode()
2. 当a.equals(b)返回true时,a.hashCode()==b.hashCode()也必须返回true
3. 一般直接将所有字段对应的散列码相加即可
4. 多数情况下会添加一个素数31,用于最大可能的保证散列码的唯一;当然31也可以换成7,11,13等(但一定是素数)。大多数人喜欢用31是因为hash*31可以被虚拟机优化为(hash<<5)-hash
代码:
class User{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@override
	public int hashCode() {
		int hash=0;
		int 
		hash=31*hash+Integer.hashCode(age);//31也可以换成7,11,13等(但一定是素数)。大多数人喜欢用31是因为hash*31可以被虚拟机优化为(hash<<5)-hash
		hash=31*hash+Objects.hashCode(name);
		return hash;
	}
}
           

四、重写toString

toString()的设计就很简单了,一般都是自定义的格式。下面是java核心思想中推荐的格式来重写的toString():
代码:
class User{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@override
	public String toString() {
		return getClass().getName()+
			"[name is:"+getName()+
			",age is:"+getAge()+
			"]";
	}
}

           

继续阅读