判斷兩個變量棧內存中存儲的值是否相等,若是相等返回true,若是不相等返回false。數組
有兩種形式的比較須要用到比較運算符「==」,一是兩個基本數據類型之間的比較,二是兩個引用數據類型之間的比較。緩存
1.兩個基本數據類型之間的比較:
性能
八大基本數據類型:byte,short,int,long,double,folat,boolean,char,其中佔一個字節的是byte和boolean,short和char佔兩個字節,int,float佔四個字節,double和long佔8個字節,這八種數據變量中直接存儲其值,變量是在棧中存儲的。this
所以:「==」比較基本數據類型時,比較的是值。spa
JAVA 基本數據類型建立單個變量是不能夠new的,由於new的都是對象。但建立基本數據類型數組時能夠new,由於數組是對象。code
int a = 5; int b = 5; int c = 6; System.out.println(a == b); // 5 == 5 System.out.println(a == c); // 5 == 6
建立了是三個基本數據類型的變量,他們在棧中存儲的值就是其數值自己,棧中值由低到高依次爲a(5)、b(5)、c(6)。所以「a==b」其本質就是「5==5」,返回true;「a==c」其本質就是「5==6」,返回false。對象
所以,運行結果依次爲:true false。blog
2.兩個引用數據類型之間的比較:
繼承
引用數據類型都是對象,通常都是在堆中被建立,變量中存儲的是堆中對象的地址引用。內存
所以,「==」比較引用類型時,比較的是地址。
這裏要注意兩個數據類型,一個是String類型,一個是Integer類型。具體請看案例分析:
String str1 = new String("abc"); // 0x123 String str2 = new String("abc"); // 0x262 String str3 = new String("xyz"); // 0x762
System.out.println(str1 == str2); // 0x123 == 0x262 System.out.println(str1 == str3); // 0x123 == 0x762
用new建立了三個String類型的對象,建立的三個對象都在堆中,所以有不一樣的地址引用。三個變量在棧中存儲的是三個對象的地址引用,其值各不相同。
所以,運行結果依次爲:false false。
String str1 = "abc"; // 0x111 String str2 = "abc"; // 0x111 String str3 = "xyz"; // 0x123 System.out.println(str1 == str2); // 0x111 == 0x111 System.out.println(str1 == str3); // 0x111 == 0x123
直接建立了三個String類型的對象,建立的字符串在字符串常量池中,所以建立已經存在的字符串會直接返回其地址引用。str2在棧中存儲的值和str1在棧中存儲的值是同樣的,都是字符串「abc」在字符串常量池中的地址引用,而str3在棧中存儲的是字符串「xyz」在字符串常量池中的地址引用。
所以,運行結果一次爲:true false。
Integer s1 = new Integer(100); Integer s2 = new Integer(100); Integer s3 = new Integer(200); System.out.println(s1 == s2); System.out.println(s1 == s3);
用new建立了三個Integer類型的對象,建立的三個對象都在堆中,所以有不一樣的地址引用。三個變量在棧中存儲的是三個對象的地址引用,其值各不相同。
所以,運行結果依次爲:false false。
Integer n1 = 100; Integer n2 = 100; System.out.println(n1 == n2); Integer a1 = new Integer(100); Integer a2 = new Integer(100); System.out.println(a1 == a2); Integer m1 = 300; Integer m2 = 300; System.out.println(m1 == m2); Integer b1 = new Integer(300); Integer b2 = new Integer(300); System.out.println(b1 == b2);
運行結果依次爲:true false false false。爲何是這樣呢?
兩個new的好解釋,由於是在堆中建立的,每一個對象有惟一的地址,所以會返回false。但第一個和第三個是啥狀況呢?
這是由於在Java中爲了提升空間和時間性能,Integer類中有一個靜態內部類IntegerCache,在IntegerCache類中有一個Integer數組,用以緩存當數值範圍爲[-128,127]時的Integer對象。因此在自動裝箱的過程當中,若是數值在[-128,127]內,會直接返回其地址引用,如果不在纔在堆中建立對象。
在Java中許多系統提供的類都定義了equals方法,這個方法用來比較兩個獨立對象的內容是否相同,而不是比較引用值自己的。自定義方法的定義大體以下(以String類爲例):
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (!COMPACT_STRINGS || this.coder == aString.coder) { return StringLatin1.equals(value, aString.value); } } return false; }
可是,若是一個自定義的類中沒有定義equals方法,那麼它將繼承Object類的equals方法,Object類的equals方法定義以下:
public boolean equals(Object obj) { return (this == obj);
}
能夠看到,若是一個類中沒有顯式的定義equals方法,那麼equals方法的做用和「==」的做用是同樣的,都是比較兩個變量指向的對象是不是同一對象。
String str1 = new String("abc"); String str2 = new String("abc"); System.out.println(str1 == str2); System.out.println(str1.equals(str2));
「==」比較的是地址,str1和str2在堆中的地址是不同的,所以結果返回false,由於String類型自定義了equals方法,此equals方法比較的是對象的內容,所以結果返回true。
因此運行結果依次爲false true。
public class Test { public Test() {} public static void main(String[] args) { Test a = new Test(); Test b = new Test(); Test c = a; System.out.println(a.equals(b)); System.out.println(a.equals(c)); } }
本身定義的的Test類,並無自定義equals方法,所以euqals方法和「==」的做用是同樣的,比較的是對象的地址,也就是說判斷兩個對象是不是同一個。a和b中存儲的地址分別是兩個不一樣對象的地址,c被賦值了a中存儲的地址,也就是說a和c指向的是同一個對象。
所以,運行結果依次是:false true。
運算符「==」只是用來比較兩個變量在棧中存放的值是否相同。
equals是類的成員方法,通常用來比較兩個獨立對象的內容是否相同(要看具體的定義)。若是自定義的類中沒有定義equals方法,則會繼承Object類的equals方法,其做用與「==」相同。