今天学习到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
这是我的学习心得,如果写得不对或者不足之处,请原谅,并指出错误,谢谢。