equals函數,hashCode(),toString()的作用和實現方法

今天學習到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


這是我的學習心得,如果寫得不對或者不足之處,請原諒,並指出錯誤,謝謝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章