關(guān)于“==”操作符
眾所周知,在Java中對于基本數(shù)據(jù)類型來說“==”操作符用于比較兩個變量的值是否相等,而對于引用類型來說“==”比較的是對象指向的引用是否一致。舉個例子,先定義一個User類:
public class User{
private String name;
private int age;
public User(String name,int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
在測試類的main函數(shù)中添加如下代碼可以得到輸出:
User user1 = new User("abc",12);
User user2 = new User("abc",12);
User user3 = user1;
System.out.println(user1==user2);//輸出false,user1和user2指向兩個不同的引用
System.out.println(user1==user3);//輸出true,user1的引用被傳遞給了user3
user3.setName("cde");//改變user3中的值
System.out.println(user1.getName());//輸出“cde”,user1與user3指向同一引用
System.out.println(user1 == user3);//輸出true,由于user1與user3兩個對象具有相同的引用,改變user3其實就是改變user1。
由此可得:當用“=”把一個引用對象賦值給另外一個引用對象后,此時使用“==”比較兩個對象返回true,兩個對象操作的是同一個引用,修改一個對象會影響另外一個對象。
關(guān)于equals方法
equals方法存在于Object類中,所以Java所有類默認都有這個方法,下面看看Object中equals方法是怎么實現(xiàn)的
public boolean equals(Object obj) {
return (this == obj);
}
從上面的代碼可以看出在Object中的equals方法是使用“==”符號比較兩個對象是否相同,所以把上一節(jié)代碼中的“==”換成equals后結(jié)果是一樣的。此時有人可能會有疑問,那為啥平時使用的String類型只要字符串一樣equals方法就返回true,那是因為String類重寫了equals方法。我們也可以重寫User類的equals方法代碼如下:
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj instanceof User){
User user = (User)obj;
if(this.name.equals(user.getName)&&this.age == user.getAge()){
return true;
}
}
return false;
}
main函數(shù)與輸出代碼如下:
User user1 = new User("abc",12);
User user2 = new User("abc",12);
User user3 = new User("cde",12);
System.out.println(user1.equals(user2));//輸出true,name和age都相等
System.out.println(user1.equals(user3));//輸出false,name不等。
從結(jié)果來看實現(xiàn)了我們想要的,但是這里面還存在一個問題,因為這個類在重寫了equals方法的同時卻沒有重寫hashCode方法,這會導(dǎo)致這個類無法與所有基于散列的集合類一起正常使用。讓我們看下面這個例子:
Map<User,String> map = new HashMap<>();
map.put(new User("xiaojian",12),"abc");
System.out.println(map.get(new User("xiaojian",12)));//輸出null,并沒有輸出我們期望的結(jié)果“abc”
上面的結(jié)果是因為上面put與get的實例雖然相等,但是他們的hashCode卻不相等,HashMap在查詢時當檢測到hashCode不一致時也不會檢驗對象的一致性。為了保證HashMap能正常工作,我們重寫User類的hashCode方法如下:
public int hashCode(){
return 17;
}
這個時候上面那段代碼輸出“abc”,得到我們期望的結(jié)果了,但這時別高興太早,由于這里返回的固定值,所有User對象都具有一個相同的hashCode,這違反了hashCode的三大原則:

那么要怎么改呢?下面是修改的一些原則:

根據(jù)這個原則修改hashCode方法如下:
public int hashCode(){
int result = 17;
result = result *31+age;
result = result * 31 + name.hashCode
}