1. 程式人生 > >關於equals與==的比較

關於equals與==的比較

最近在學習中遇到一個問題,兩個值相同的Integer型值進行==和equals比較時,發現了其中一些詭異的地方,然後就學習了一下有關Integer自動拆裝箱和常量池的概念

 

先來一個demo說明詭異在何處:

package cn.java.test;

public class demo {
	public static void main(String[] args) {
		
		System.out.println("先用Integer i = x的方式為Integer物件賦值");
		Integer i1 = 127;
		Integer i2 = 127;
		System.out.println(i1==i2);
		System.out.println(i1.equals(i2));
		
		Integer i3 = 128;
		Integer i4 = 128;
		System.out.println(i3==i4);
		System.out.println(i3.equals(i4));
		
		System.out.println();
		System.out.println();
		
		System.out.println("再用Integer i = new Integer(x)的方式為Integer物件賦值");
		Integer i5 = new Integer(127);
		Integer i6 = new Integer(127);
		System.out.println(i5==i6);
		System.out.println(i5.equals(i6));
		
		
		Integer i7 = new Integer(128);
		Integer i8 = new Integer(128);
		System.out.println(i7==i8);
		System.out.println(i7.equals(i8));
		
	}
}

結果如下:

先用Integer i = x的方式為Integer物件賦值
true
true
false
true


再用Integer i = new Integer(x)的方式為Integer物件賦值
false
true
false
true

首先了解一下,==比較的是兩個物件的地址 ,而equals比較的是兩個物件的具體的數值的大小。所以也不難解釋此demo中的所有的物件的equals的比較都為true了。所以接下來我們思考這個“==”的問題

此時便引出了思考了:

為什麼用Integer i = x的方式為Integer物件賦值的時候,

為Integer賦值為127的兩個物件的時候,i1==i2;的結果為true,也就是說這兩個數值為127的物件的地址一樣,

為Integer賦值為128的兩個物件的時候,i3==i4的地址卻為false,也就是說這兩個數值為128物件的地址不一樣。

 

當用Integer i = new Integer(x)的方式為Integer物件賦值的時候,

當分別new兩個數值127的物件的時候,i5==i6的結果為false;也就是說這兩個數值為127的物件的地址不一樣,

當分別new兩個數值128的物件的時候,i7==i8的結果為false;也就是說這兩個數值為127的物件的地址不一樣,

最後探其究竟發現原因如下:

因為Integer的數值在-128~127之間時,即在int的範圍內,預設是按照基本型別int來存放的,即用的是原生資料型別int,仍舊存在堆疊中,會在記憶體裡供重用,也就是說這之間的Integer值進行==比較時只是進行int原生資料型別的數值比較。在java裡面,當類載入時就將-128 到 127 的Integer物件建立了,並儲存在cache陣列中,一旦程式用Integer i = x的方式為Integer物件賦值的時候

,如果i的值是在-128 到 127 之間就直接在cache快取陣列中去取Integer物件而不是自己去建立一個新的物件。而cache中的物件,建立完了之後的地址是不變的,故在-128到127這個範圍內的數值相等的Integer的物件的地址都相等。

而如果超出了int的範圍,用Integer i = x的方式為Integer物件賦值的時候,就按照物件的方式來存放和比較了,虛擬機器會自動建立一個新的物件,賦值多少次就建立多少次,而每建立一個新的物件,其地址肯定不一樣,故超範圍的Integer物件的地址不一樣。

這也就解釋了上面的結果了。

再給大家拓展一下String型別的有關==和equals的比較:

package cn.java.test;

public class demo {
	public static void main(String[] args) {
		
		String s = "abc";
		String s1 = "abc";
		String s2 = new String("abc");
		
		System.out.println(s==s1);            //結果為true
		System.out.println(s.equals(s1));     //結果為true
		System.out.println(s==s2);            //結果為false
		System.out.println(s.equals(s2));     //結果為true
		
		
	}
}

解釋:
 

 

String s = "abc";

這裡的"abc"稱為字串常量,也是存在堆疊中的,s中存放的就是指向這個堆疊地址的引用,如果再定義一個

String s1 = "abc";

這時,s與s1存放的是同一個地址的引用,即s與s1指向的是同一個字串常量,

s == s1的值是true,

但是如果有

String s2 = new String("abc");

這時s == s2則為false,因為使用new之後,每次生成的物件都不是同一個,即使儲存的內容相同。

上面的s == s1,s == s2其實比較的都是地址,並不是裡面的內容。如果要比較內容,可以使用equals()方法。