先看一段代碼:數組
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.