1. 程式人生 > >關於java ==,equal() 以及 hashcode()

關於java ==,equal() 以及 hashcode()

1.首先,'=='  大家都很熟悉就是比較地址,話不多說直接上程式碼 :

public class Demo {
	public static void main(String[] args){
		String s1 = "123";
		String s2 = "123";
		String s3 = new String("123");
		System.out.println(s1==s2);//輸出 true
		System.out.println(s3==s1);//輸出 false
	}
}

上述程式碼,

    首先簡單瞭解一下棧 和 常量池:

    1>.棧:存放基本型別的

變數資料和物件的引用,但物件本身不存放在棧中,而是存放在堆(new 出來的物件)或者常量池中(字串常量物件存放在常量池中)。

    2>.常量池:存放字串常量和基本型別常量( public static final ,java存放字串用 public final 修飾的value陣列 )

s1,s2都是常量,其後面的 "123" 都被放在常量池中,其實在 s2 建立的時候,只是把已經在常量池中的 "123"賦值給了s1引用變數,這樣s1當然等於s2啦,因為兩者是一個東西,當然地址也相同。

至於s3為什麼不等於s1,那是因為,s3是new出來的,也就是說s3new出來的物件在堆中,s3這個引用變數在棧中,但是s1的物件在常量池中,這兩個當然地址不一樣啦!


2. equals方法 

    1>.首先上未經重寫的equals原始碼,也就是Object中的 equals 方法:

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

上述程式碼,大家不難看出,要比較兩個引用變數所指物件的地址。

    2>.接下來,上String型別重寫過後的equals方法:

   public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

由上述程式碼不難看出,首先java 先比較兩個字串的地址是否相同,如果相同,那麼就直接返回true;

接下來,如果地址不相同,那麼分別獲取兩個字串對應的 char 陣列,進行遍歷比較每個字元是否相等,如果有一個不相等就返回false,否則就返回true。

注意:java已經將大部分類都重寫了equals方法!!! 只有少部分不需要用到equals的,才沒重寫。


3.hashcode() 方法

寫這個之前,我先說一下我之前遇到的一個小問題:

public class Demo {
	public static void main(String[] args){
		String a= null;
		System.out.println(a.hashCode());
	} 
}

這段程式碼報錯 

Exception in thread "main" java.lang.NullPointerException
	at ttms.Demo.main(Demo.java:6)
之後我找到了String類重寫的 hashCode() 的原始碼:
  public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

上述程式碼中會呼叫 value.length變數,value就是你的字串轉換成的字元陣列,那麼問題就簡單了,你傳進去的物件就是空的,那就肯定沒有length屬性啦,也就會報空指標異常。

補充一下:如果沒有重寫hashcode方法,那麼就返回的是物件的32位jvm記憶體地址。