Java的==和equals()以及自動裝箱拆箱
拋一個問題
大家先看下面的代碼,先不要看答案自己做一下:
public class AutoboxingTest {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c == (a + b));
System.out.println(c.equals(a + b));
System.out.println(g == (a + b));
System.out.println(g.equals(a + b));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
然後和正確答案對比一下:
如果全部正確證明你這塊知識掌握的很牢固,沒有必要在看下去了,如果你發現自己有做錯的地方法,那麽耐心的看下去吧。
先說一說 == 和 equals()方法
==
- 對於基本類型,不包含基本類型的包裝類型,比較的是基本類型的值。
- 對於對象來說,== 比較的是兩個對象在內存中的地址。
equals()方法
equals()是Object對象中的方法:
這是在Object對象中的實現,因為所有的類都繼承於Object類,一般都會重寫這個方法,實現不同,比較的方式就不同,這個方法主要就是實現對象在邏輯上的相等,而這個邏輯是由你決定的。
下面是Integer類中的equals()方法:
這裏首先判斷比較的對象是否是Integer,如果是則強制轉換成Integer,然後比較它們的值,如果類型不同直接返回false。
再說一下Integer的緩存機制
從Java1.5 開始,Integer類型是有緩存對象的:
緩存對象IntegerCache是Integer中的一個靜態內部類,緩存的範圍是-128~127。
經過我對源碼的探究,發現並不是只用Integer有緩存機制,所有整數類型的類都有類似的緩存機制。
Class | CachaClass | Range |
---|---|---|
Character | CharacterCache | 0~127 |
Byte | ByteCache | -128~127 |
Short | ShortCache | -128~127 |
LongCache | LongCache | -128~127 |
Integer | IntegerCache | -128~127 |
除了 Integer 可以通過參數改變範圍外,其它的都不行。
通過CharacterCache和IntegerCache的初始化源碼可以說明這個問題。
自動裝箱和自動拆箱
自動裝箱
當你用基本類型的值給它的包裝類賦值時,系統會自動將基本類型轉換成它的包裝類型。
例如:Integer i = 1,這時候系統就將1賦值給Integer類型的i。使用的時Integer的valueOf()方法。
首先會判斷值是否在low和high之前,也就是說是否已經存在一個緩存對象的值和當前的值相同,如果存在直接返回該對象,否則重新new一個對象。
自動拆箱
和自動裝箱相反,當你需要基本類型的時候,系統也會自動的將包裝類轉換成基本類型。
例如:
Integer a1=1;
int a2 = a1;//這時候系統就會將Integer類型的a1自動拆箱,把值取出來賦值給a2
- 1
- 2
這個時候系統調用的是Integer的intValue()方法:
就是直接返回值。
再來看之前那個問題就很簡單了
-
c==d 是true。c和d都是緩存對象3,就是同一個對象,所以相等。
-
e==f 是false。e和f都超出緩存對象的範圍,都是new的新的對象,是不同的對象所以在內存中的地址肯定不同,所以是false。
-
c == (a + b) ,這個就要註意了,在含有算術運算的時候,會進行自動拆箱的操作,也就是說這裏比較的是c的值和a+b的值的關系。
開始的時候我以為a+b的值是3,然後這個3是緩存對象,所以相等,但是我在Debug跟進的時候,發現調用了3次Integer.intValue(),然後去查了查,發現在算術運算的時候,會進行自動拆箱的操作。
-
c.equals(a + b) 這個就是調用Integer的equals()方法,先對a和b進行了自動拆箱的操作,然後將他們的和進行自動裝箱操作,然後調用equals()方法比較,因為Integer的equals()方法已經重寫過了,上面已經介紹過了,比較的是兩個對象的值,所以返回true。
-
g == (a + b) 這個首先會像第4個一樣,首先會對g進行自動拆箱,然後對a和b進行自動拆箱的操作,之後進行它們值的比較,這時候還會發生隱式類型轉換,int → long。因為值一樣,所以返回true。
-
g.equals(a + b) 這個調用Long的equals()方法,而a+b的類型是Integer,所以會返回false。
Java的==和equals()以及自動裝箱拆箱