1. 程式人生 > >Java的==和equals()以及自動裝箱拆箱

Java的==和equals()以及自動裝箱拆箱

char AC oid name span 兩個 也會 掌握 word

拋一個問題

大家先看下面的代碼,先不要看答案自己做一下:

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()方法

==

  1. 對於基本類型,不包含基本類型的包裝類型,比較的是基本類型的值。
  2. 對於對象來說,== 比較的是兩個對象在內存中的地址。

equals()方法

equals()是Object對象中的方法:
技術分享圖片
這是在Object對象中的實現,因為所有的類都繼承於Object類,一般都會重寫這個方法,實現不同,比較的方式就不同,這個方法主要就是實現對象在邏輯上的相等,而這個邏輯是由你決定的。

下面是Integer類中的equals()方法:
技術分享圖片
這裏首先判斷比較的對象是否是Integer,如果是則強制轉換成Integer,然後比較它們的值,如果類型不同直接返回false。

再說一下Integer的緩存機制

從Java1.5 開始,Integer類型是有緩存對象的:
技術分享圖片
緩存對象IntegerCache是Integer中的一個靜態內部類,緩存的範圍是-128~127。

經過我對源碼的探究,發現並不是只用Integer有緩存機制,所有整數類型的類都有類似的緩存機制。

ClassCachaClassRange
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()方法:
技術分享圖片

就是直接返回值。

再來看之前那個問題就很簡單了

    1. c==d 是true。c和d都是緩存對象3,就是同一個對象,所以相等。

    2. e==f 是false。e和f都超出緩存對象的範圍,都是new的新的對象,是不同的對象所以在內存中的地址肯定不同,所以是false。

    3. c == (a + b) ,這個就要註意了,在含有算術運算的時候,會進行自動拆箱的操作,也就是說這裏比較的是c的值和a+b的值的關系。

      開始的時候我以為a+b的值是3,然後這個3是緩存對象,所以相等,但是我在Debug跟進的時候,發現調用了3次Integer.intValue(),然後去查了查,發現在算術運算的時候,會進行自動拆箱的操作。

    4. c.equals(a + b) 這個就是調用Integer的equals()方法,先對a和b進行了自動拆箱的操作,然後將他們的和進行自動裝箱操作,然後調用equals()方法比較,因為Integer的equals()方法已經重寫過了,上面已經介紹過了,比較的是兩個對象的值,所以返回true。

    5. g == (a + b) 這個首先會像第4個一樣,首先會對g進行自動拆箱,然後對a和b進行自動拆箱的操作,之後進行它們值的比較,這時候還會發生隱式類型轉換,int → long。因為值一樣,所以返回true。

    6. g.equals(a + b) 這個調用Long的equals()方法,而a+b的類型是Integer,所以會返回false。

Java的==和equals()以及自動裝箱拆箱