Amazon Ads

2012年10月30日 星期二

Java String 的「==」和「equals」

今天同事問了一個Java String比較的問題,讓我想起剛學Java時,也有的相同疑惑!

在Java中,字串是使用String類別來建構,請參考Java Gossip: String 類別一個字串物件一旦被配置,它的內容就是固定不可變的(immutable),也就是說,當指定了兩個String變數後,他在記憶體中,是兩個由兩個不同的記憶位置,指向不同的記憶體區塊。
如:
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println("s3 == s4 ? " + (s3 == s4)); //印出false
System.out.println("s3 equals s4 ? " + (s3.equals(s4)));  //印出true
由上例,可以知道:若要比對字串內容是不是相等,要使用equals,來看看String類別中,equals方法的實作:
    /**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    public boolean equals(Object anObject) {
       if (this == anObject) {
           return true;
       }
       if (anObject instanceof String) {
           String anotherString = (String)anObject;
           int n = count;
           if (n == anotherString.count) {
               char v1[] = value;
               char v2[] = anotherString.value;
               int i = offset;
               int j = anotherString.offset;
               while (n-- != 0) {
                   if (v1[i++] != v2[j++])
                       return false;
               }
               return true;
           }
       }
       return false;
    }
那你是否會問,用「==」去比較兩個String變數,是什麼意思?其實,就是去看這兩個變數所指向的記憶體位置是否相同。有興趣的可以參閱http://www3.ntu.edu.sg/home/ehchua/programming/java/J3d_String.html,這裡對String有更進一步的說明。

另外,值得一提的是,若你在同一程式區塊中,不用new的方式,而是直接用""的方式設定字串變數的話,用「==」是會回傳true的,如:
public static void main(String[] argv){
 String s1 = "Hello";
 String s2 = "Hello";
 String s0 = get();
 System.out.println("s1 == s2 ? " + (s1 == s2));//印出true
 System.out.println("s0 == s1 ? " + (s0 == s1));//印出true
        System.out.println("s0 == s2 ? " + (s0 == s2));//印出true
}

private static String get(){
 return "Hello";
}

這是Java為String設計的一個特別叫「string common pool」的機制,在上列的網頁中有說明,主要是對常用的字串保留記憶體空間,來節省使用的空間,在上列中,對於"Hello"字串,會在記憶體中產生一個String物件,讓s1、s2、s0都指向它,所以用「==」去比較時,都會回傳true。