equals函数,hashCode(),toString()的作用和实现方法

时间:2022-06-06 16:22:36

今天学习到equals函数的作用,这里就写下我的心得吧。

首先先了解一下双等号“==”的作用

双等号“==”用来比较引用数据类型的时候,就判断双等号“==”两边的引用是否指向堆内存的同一块地址,

或者说是否指向堆内存里的同一个对象。

User.java

class User {
String name;
int age;
}

Test.java

class Test{
public static void main(String[] args){
User u1 = new User();
User u2 = new User();
User u3 = u1;

boolean b1 = u1 == u2;
boolean b2 = u1 == u3;
System.out.println(b1);
System.out.println(b2);
}
}
为什么要先举双等号的例子呢,因为双等号的作用和这次学的equals函数的作用很容易混淆。

先说一下这里的结果,结果是第一个false第二个true


这一次要学习的是equals函数,它用来比较两个对象的内容是否相等

通常情况下,对象的内容相等需要符合两个条件:

1.对象的类型相同(可以使用instanceof操作符进行比较);

2.两个对象的成员变量的值完全相同;

这里需要注意的是,我们在使用equals函数的时候,不能直接调用obj的equals函数,而是应该自己复写一个,因为obj的equals函数实际上也是用的双等号比较,

所以我们需要复写equals函数

User.java

class User {
String name;
int age;

public boolean equals(Object obj){
if(this == obj){
return true;
}

boolean b = obj instanceof User;
if(b){
User u = (User)obj;
if(this.age == u.age && this.name.equals(u.name)){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
}

比较基本数据类型的时候直接用双等号比,而比较引用数据类型的时候就用equals比,因为引用数据类型有定义相应的equals函数。


Test.java

class Test{
public static void main(String[] args){
User u1 = new User();
User u2 = new User();
User u3 = new User();

u1.name = "zhangsan";
u1.age = 12;

u2.name = "lisi";
u2.age = 12;

u3.name = "zhangsan";
u3.age = 12;

System.out.println(u1.equals(u2));
System.out.println(u1.equals(u3));
}
}

这样就把equals复写成功,并测试成功了。

明显可以看出,u1和u2是不同的,而u1跟u3是符合要求的。所以应返回

false 

true


hashCode()和toString()都存在于Object这个类中。所有类都从Object中继承了这两个方法

Hash算法,是指将任意长度的数据(二进制)通过Hash算法,能生成唯一的散列值,

User.java

class User{
String name;
int age;

public User(){

}

public User(String name,int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
if(this == obj){
return true;
}

if(obj instanceof User){
User u = (User)obj;
if(this.age == u.age && this.name.equals(u.name)){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
}

Test.java

import java.util.*;

class Test{
public static void main(String[] args){
User u = new User("zhangsan",12);

HashMap<User,String> map = new HashMap<User,String>();
map.put(u,"abc");

String s = map.get(new User("zhangsan",12));
System.out.println(s);
}
}

照理说,键为u,保存了键值为abc,而我们用get提取的时候应该也是abc才对,但结果却是null、

由于我们没有复写hashCode(),所以它们返回的hash码是不一样的。

修改User.java,复写hashCode();

class User{
String name;
int age;

public User(){

}

public User(String name,int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
if(this == obj){
return true;
}

if(obj instanceof User){
User u = (User)obj;
if(this.age == u.age && this.name.equals(u.name)){
return true;
}
else{
return false;
}
}
else{
return false;
}
}

public int hashCode(){
return 12;
}
}

Test.java不变,编译运行,结果就是abc.

这里复写的hashCode是简单的。

下面有另外一种复写

User.java

class User{
String name;
int age;

public User(){

}

public User(String name,int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
if(this == obj){
return true;
}

if(obj instanceof User){
User u = (User)obj;
if(this.age == u.age && this.name.equals(u.name)){
return true;
}
else{
return false;
}
}
else{
return false;
}
}

public int hashCode(){
int result = 11;

result = 31 * result + age;
result = 31 * result + name.hashCode();
return result;
}
}

下面介绍toString()用法,User.java不变,Test.java改为

import java.util.*;

class Test{
public static void main(String[] args){
User u = new User("zhangsan",12);

System.out.println(u);
}
}

这里的System.out.println(u);是先运行u.toString(),然后再打印出来的。


这时编译运行的结果是

User@aa9c5b33

而这个toString()也是可以复写的。

同样方法,在User.java下面加

public String toString(){
String result = "age:" + age + "," + "name:" + name;
return result;
}

这样就可以了。运行结果是

age:12,name:zhangsan


这是我的学习心得,如果写得不对或者不足之处,请原谅,并指出错误,谢谢。