Java中「==」和 equals的區別

「==」的做用:

判斷兩個變量棧內存中存儲的值是否相等,若是相等返回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.兩個引用數據類型之間的比較:
繼承

  引用數據類型都是對象,通常都是在堆中被建立,變量中存儲的是堆中對象的地址引用。內存

  所以,「==」比較引用類型時,比較的是地址。

  • 通常的類用new來建立對象,是在堆中開闢空間來存儲的,每一個對象都有惟一的地址;
  • 數據類型的包裝類既能夠用new來建立,在堆中開闢空間存儲,也能夠直接建立,經過自動裝箱的機制來完成對象在堆中的建立。

  這裏要注意兩個數據類型,一個是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]內,會直接返回其地址引用,如果不在纔在堆中建立對象。

equals的做用:

  在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方法,其做用與「==」相同。

相關文章
相關標籤/搜索