今天學習到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
這是我的學習心得,如果寫得不對或者不足之處,請原諒,並指出錯誤,謝謝。