1. 程式人生 > >自動裝箱和==和equals

自動裝箱和==和equals

靜態數組 fin mat ble 而且 equals 數值 str comment

一,"=="和equals

首先我們明確一下"=="和equals方法的作用。

  1. ==

如果是基本數據類型,則直接對值進行比較

基本類型和包裝類比較,進行自動拆箱操作

如果是引用數據類型,則是對他們的地址進行比較

但是只能比較相同類型的對象,或者比較父類對象和子類對象

基本數據類型和包裝類算同一類型,和其他類型不是同一類型

  1. equals方法繼承自Object類
  • Object中equals的源碼實現是對對象的地址進行比較,此時它和"=="的作用相同。

  • JDK類中有一些類覆蓋了Object類的equals()方法 比較規則為:如果兩個對象的類型一致,並且內容一致,則返回true,這些類有:

java.io.file

java.util.Date

java.lang.string

包裝類(Integer,Double等)

二,實驗

Java的自動拆箱和裝箱是Java語言的一顆語法糖。看下面的代碼:

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;
    int x = 3;
    long y = 3L;
    
    //x,y雖然類型不同但是可以直接進行數值比較
    System.out.println(x == y);
    //System.out.println(c == g); 提示出錯,不可比較的類型。說明此時沒有自動拆箱
    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));
}

答案:

  • T
  • T
  • F
  • T
  • T
  • T
  • F

三,自動拆箱

"=="在遇到非算術運算符的情況下不會自動拆箱,以及他們的equals方法不處理數據類型轉換的關系。

因此,

  1. 對於 System.out.println(c == d);

int值在-128--127之間,他們指向同一個對象,返回True。

  1. 對於 System.out.println(e == f);

integer值大於127,對應不同的內存地址,返回false。

  1. System.out.println(c == g);

提示出錯,不可比較的類型。說明此時沒有自動拆箱

==不能對不同類型進行比較

  1. 對於 System.out.println(e.equals(f));

equals方法:值相同,而且類型相同,返回true。

  1. 對於 System.out.println(c == (a+b));

integer和int相比,自動拆箱後他們的值是相等的,返回True。

  1. 對於 System.out.println(c.equals(a+b));

equals方法:值相同,而且類型相同,返回true。

  1. 對於 System.out.println(g == (a+b));

自動拆箱後他們的值相等,返回True。

  1. 對於 System.out.println(g.equals(a+b));

他們的值相同但是類型不同,返回false。

四,源碼:一個靜態數組保存了-128-127範圍內的數據

Java的包裝類實現細節。觀察源碼會發現Integer包裝類中定義了一個私有的靜態內部類如下:

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

通過觀察上面的代碼我們可以發現:

Integer使用一個內部靜態類中的一個靜態數組保存了-128-127範圍內的數據,靜態數組在類加載以後是存在方法區的,並不是什麽常量池。

在自動裝箱的時候,首先判斷要裝箱的數字的範圍,如果在-128-127的範圍則直接返回緩存中已有的對象,否則new一個新的對象。

其他的包裝類也有類似的實現方式,可以通過源碼觀察一下。

五,總結

對於不懂的地方,最好是通過閱讀源碼的方式來解決。這樣才能真正明白內部的一些實現方式。

自動裝箱和==和equals