Java自動裝箱和拆箱

自動裝箱和拆箱定義

自動裝箱:把基本類型用其包裝類替代,使其具有對象的特性??梢哉{(diào)用toString()、hashCode()、getClass()、equals()等方法。編譯器調(diào)用的是valueOf這個方法即:

Integer a = Integer.valueOf(4);

自動拆箱:將包裝類轉(zhuǎn)換為基本類型。
由于裝箱和拆箱是自動進行的非人為轉(zhuǎn)換,所以就稱作為自動裝箱和拆箱。編譯器調(diào)用的是intValue方法即:

int a = new Integer(4).intValue

原始類型:byte,short,char,int,long,float,double,boolean
封裝類:Byte,Short,Character,Integer,Long,Float,Double,Boolean

發(fā)生時機

當出現(xiàn)賦值運算、算術(shù)表達式、方法調(diào)用等情況時,會觸發(fā)自動裝箱/拆箱操作,舉例如下

Integer a = 1;
Integer b = 2;
Long c = 3L;
System.out.println(c == (a+b));
System.out.println(c.equals(a+b));

輸出結(jié)果如下:

true
false

分析如下:
c==(a+b),算數(shù)表達式先運算a+b拆箱操作,得到數(shù)值為3。Long與int比較,會自動拆箱,因此最終是3==3,得到值為true
c.equals(a+b),a+b拆箱操作,得到數(shù)值為3int類型。Long與int進行equals,由于不是同一個對象,因此會返回false。
第二種情況可以查看源碼,在Long對象源碼中,equals首頁需要判斷是否是同一對象

public boolean equals(Object obj) {
        if (obj instanceof Long) {
            return this.value == (Long)obj;
        } else {
            return false;
        }
    }

包裝類緩存

查看包裝類源碼,對于byte short int long char boolean這些類型的包裝類都實現(xiàn)了一個字節(jié)的緩存,float double這兩種類型沒有緩存。因此在緩存范圍內(nèi)的包裝類,使用==時實際是同一對象

Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i1 == i2); //true  滿足緩存訪問
System.out.println(i3 == i4);//false 在緩存范圍之外

Double d1 = 127.0;
Double d2 = 127.0;
Double d3 = 128.0;
Double d4 = 128.0;
System.out.println(d1 == d2);//false 沒有緩存
System.out.println(d3 == d4);//false 沒有緩存

實現(xiàn)包裝類緩存源碼如下:

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

        private IntegerCache() {
        }

        static {
            int h = 127;
            String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            int size;
            if (integerCacheHighPropValue != null) {
                try {
                    size = Integer.parseInt(integerCacheHighPropValue);
                    size = Math.max(size, 127);
                    h = Math.min(size, 2147483518);
                } catch (NumberFormatException var6) {
                }
            }

            high = h;
            VM.initializeFromArchive(Integer.IntegerCache.class);
            size = high - -128 + 1;
            if (archivedCache == null || size > archivedCache.length) {
                Integer[] c = new Integer[size];
                int j = -128;

                for(int k = 0; k < c.length; ++k) {
                    c[k] = new Integer(j++);
                }

                archivedCache = c;
            }

            cache = archivedCache;

            assert high >= 127;

        }
    }

這里使用了享元模式

包裝類的意義

其實這個問題才是最關(guān)鍵的,一個知識點的存在的意義才是我們更深入了解它的關(guān)鍵,才能在使用時因地制宜
1、如果你想在方法體內(nèi)更新primitive類型即原始類型的值,必須要使用primitive對應(yīng)的object,因為前者使用的值傳遞,后者使用的是引用傳遞
2、java.util內(nèi)操作的都是對象,如果沒有PWC,會讓程序員在使用這些工具類操作原始類型時編寫額外的代碼
3、Java提供的集合框架中的數(shù)據(jù)結(jié)構(gòu),比如ArrayList和Vector,也是只能操作對象,理由和第二點相似
4、多線程中也必須使用對象來完成各種同步操作
5、從設(shè)計理念上,在Java中,萬物皆對象,為原始類型設(shè)計出與之匹配的對象類型,更能讓編程體驗與審計理念融為一體
所以基于上述五點考慮,包裝類的存在是有積極意義的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容