String類的一些細節

先看一段代碼:數組

    public static void main(String[] args) {
        String a = "a"+"b"+1;
        String b ="ab1";
        System.out.println(a == b);
    }優化

輸出的結果是true.this

 

1.==和equals的區別spa

(1).基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 他們之間的比較,應用雙等號(==),比較的是他們的值。
(2).複合數據類型(對象類型),當他們用(==)進行比較的時候,比較的是他們在內存中的存放地址,因此,除非是同一個new出來的對象,他們的比較後的結果爲true,不然比較後結果爲false。 JAVA當中全部的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行爲是比較對象的內存地 址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date在這些類當中equals有其自身的實現,而再也不是比較類在堆內存中的存放地址了。
 對於複合數據類型之間進行equals比較,在沒有覆寫equals方法的狀況下,他們之間的比較仍是基於他們在內存中的存放位置的地址值的,由於Object的equals方法也是用雙等號(==)進行比較的,因此比較後的結果跟雙等號(==)的結果相同。
對象

2.編譯時優化繼承

當編譯器在編譯代碼String a="a"+"b"+1;時,會將其編譯爲:String a="ab1";這是爲了提高總體工做效率JVM進行的優化。相似的優化還有不少,例如當程序中出現int i=3*4+120時,會在編譯時就變成了i=132。
但須要注意的是,JVM只優化能夠優化的部分,即在編譯階段就能夠肯定值的,若是字符串中出現了變量,那麼JVM是不會作這樣的編譯時優化的。例如:
內存

String a="a";字符串

final String c="a";get

String b=a+"b";編譯器

String c=c+"b";

String e=getA()+"b";

String d="ab";

String f = new String(b);

其中b和e在編譯時不會被優化,而c會被優化,由於c是final變量,可認爲是常量。因此b==d,e==d爲false,c==d爲true.

3.常量池

程序在運行的時候會建立一個常量池,它保證同一個值的字符串全局惟一。當使用 String b = "ab1", 這樣的表達是建立字符串的時候,程序首先會在這個常良池中尋找相同值的對象,在程序中,a引用的對象先被放到了池中,因此在b被建立的時候,將使b也指向這個對象。因此a==b爲true.
String 類有個intern方法,當調用它時,JVM會在常良池中經過equals方法查找是否存在等值的String,若是存在,則直接返回常量池中這個String對象的地址;若是不存在,則會在常良池中建立等值的字符串,而後再返回這個新建立空間的地址。所以,只要是一樣的字符串,當調用intern方法時,都會獲得常良池中對應String對象的地址。因此上面雖然b==d爲false,可是b.intern()==d爲true.

 

4.String類的equals方法實現。

前面說過, 對於複合數據類型之間進行equals比較,在沒有覆寫equals方法的狀況下,他們之間的比較仍是基於他們在內存中的存放位置的地址值的,但String,Integer,Date在這些類當中equals有其自身的實現,所以再也不是比較類在堆內存中的存放地址了。下面是String類的equals方法實現:

public boolean equals(Object anObject)
{

      //一、若是是同一個對象,直接返回true
        if (this == anObject)
        {
            return true;
        }
        //二、若是傳遞進來的參數類型不是String,直接返回false
        if (anObject instanceof String)
        {
            String anotherString = (String)anObject;
            int n = count;//字符串長度
            if (n == anotherString.count) //三、若是長度不相等,直接返回false
            {
                char v1[] = value;//取每個位置的字符
                char v2[] = anotherString.value;
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) //四、循環對比兩個字符串的char數組,逐個比較字符是否一致,若存在不一致的狀況,直接返回false
                {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;//五、循環結束都沒有找到不匹配的,說明兩個字符串相等,返回true.
            }
        }
        return false;
}

 

在上例中,f==d爲false,由於內存地址不同,可是f.equals(d)爲true.

相關文章
相關標籤/搜索