裝箱(Autoboxing)和拆箱(Unboxing)

裝箱(Autoboxing)和拆箱(Unboxing)

wiki

學(xué)習(xí)目標(biāo)

  • Why:為什么需要裝箱和拆箱;
    • 代碼更加簡潔
    • 基本數(shù)據(jù)類型可以使用泛型
  • What:什么是裝箱和拆箱;
  • How:裝箱和拆箱是怎么實現(xiàn)的插勤?
    • 裝箱:包裝類的valueOf()方法
    • 拆箱:包裝類的***Value()方法
  • When:什么時候使用裝箱和拆箱
  • Where:在什么地方會使用到裝箱和拆箱
  • Other:裝箱和拆箱的優(yōu)點和缺點
    • 優(yōu)點:代碼簡潔叹洲,可以使用泛型
    • 缺點:裝箱需要創(chuàng)建新的對象,時間會比較長

裝箱和拆箱的定義

  • 裝箱(Autoboxing):基本數(shù)據(jù)類型(int绍填,double等)轉(zhuǎn)換為對應(yīng)的包裝類叫做裝箱;
    • 基本數(shù)據(jù)類型作為參數(shù)傳遞給一個用對應(yīng)包裝類作為參數(shù)的方法時使用裝箱;
    • 將基本數(shù)據(jù)類型賦值給對應(yīng)的包裝類媳溺;
  • 拆箱(Unboxing):包裝類轉(zhuǎn)換為對應(yīng)的基本數(shù)據(jù)類型叫做拆箱掀泳;
    • 將包裝類作為參數(shù)傳遞給一個用對應(yīng)基本數(shù)據(jù)類型作為參數(shù)的方法時使用裝箱雪隧;
    • 將包裝類賦值給對應(yīng)的基本數(shù)據(jù)類型;
Interger i = 10; //裝箱
int num = i; //拆箱

基本數(shù)據(jù)類型和對應(yīng)的包裝類

Primitive Type Wrapper Class
boolean Boolean
byte Byte
char Character
float Float
int Integer
long Long
short Short
double Double

為什么需要拆箱和裝箱

  • 在泛型中员舵,編譯器會進(jìn)行類型擦除脑沿,將泛型中的類型編譯為Object;對應(yīng)基礎(chǔ)數(shù)據(jù)類型马僻,無法使用泛型庄拇,比如創(chuàng)建列表,即不能出現(xiàn)List<int>, List<long>;通過裝箱和拆箱韭邓,可以將int類型加入List<Integer>中措近,其他類型類似

    public static void main(String[] args)
    {
        int i = 1;
        List<Integer> list = new ArrayList<Integer>();
        list.add(i);
    }
    

    編譯后代碼

    public static void main(String[] args) {
        int i = 1;
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(Integer.valueOf((int)i));
    }
    

裝箱和拆箱是怎么實現(xiàn)的?

public static void main(String[] args)
{
    Integer i = 10;

    int n = i;
}
  • 使用命令java -jar .\cfr_0_132.jar .\BoxingTest.class --sugarboxing false > BoxingTest.txt反編譯上述代碼

    public static void main(String[] args) {
            Integer i = Integer.valueOf((int)10);
            int n = i.intValue();
        }
    
  • 裝箱是利用包裝類的valueOf()方法女淑;

  • 拆箱是利用包裝類的***Value()方法瞭郑;

包裝類的valueOf()方法

public static void main(String[] args) {

    Integer i1 = 100;
    Integer i2 = 100;
    Integer i3 = 200;
    Integer i4 = 200;

    System.out.println(i1==i2); // true
    System.out.println(i3==i4); // false
}
  • 查看Integer.valueOf()方法

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    
    • valueOf方法可以看出,如果數(shù)字在[-127,128]之間鸭你,不會新建Integer類屈张,會直接返回緩存中已經(jīng)創(chuàng)建的對象的引用;
public static void main(String[] args)
{
    Double d1 = 10.0;
    Double d2 = 10.0;

    System.out.println(d1 == d2); // false
}
  • 查看Double.valueOf()方法

    public Double(double value) {
        this.value = value;
    }
    
    • 由于double類型的值不是離散的袱巨,無法使用緩存保存袜茧;
  • Integer、Short瓣窄、Byte笛厦、Character、Long這幾個類的valueOf方法的實現(xiàn)是類似的俺夕;

    類型 包裝類緩存范圍
    Integer裳凸,Byte,Short劝贸,Long [-128,127]
    Character [0,127]
    Double姨谷,F(xiàn)loat
  • Double、Float的valueOf方法的實現(xiàn)是類似的

when and where: 使用裝箱和拆箱

public static void main(String[] args)
{
    Integer i1 = 1;
    Integer i2 = 2;
    Integer i3 = 3;
    System.out.println(i3 == (i1 + i2)); // true

    Long l1 = 3l;
    Long l2 = 2l;
    System.out.println(l1 == (i1 + i2)); // true
    System.out.println(l1.equals(i1 + i2)); // false
    System.out.println(l1.equals(i1 + l2)); // true
}

cfr編譯后的代碼

public static void main(String[] args) {
    Integer i1 = Integer.valueOf((int)1);
    Integer i2 = Integer.valueOf((int)2);
    Integer i3 = Integer.valueOf((int)3);
    System.out.println((boolean)(i3.intValue() == i1.intValue() + i2.intValue()));
    
    Long l1 = Long.valueOf((long)3L);
    Long l2 = Long.valueOf((long)2L);
    System.out.println((boolean)(l1.longValue() == (long)(i1.intValue() + i2.intValue())));
    System.out.println((boolean)l1.equals((Object)Integer.valueOf((int)(i1.intValue() + i2.intValue()))));
    System.out.println((boolean)l1.equals((Object)Long.valueOf((long)((long)i1.intValue() + l2.longValue()))));
}
  • 當(dāng) "=="運算符的兩個操作數(shù)都是包裝器類型的引用映九,則是比較指向的是否是同一個對象梦湘;而如果其中有一個操作數(shù)是表達(dá)式(即包含算術(shù)運算)則比較的是數(shù)值(即會觸發(fā)自動拆箱的過程);
  • 包裝器類型中equals()方法中并不會進(jìn)行類型轉(zhuǎn)換。

三目運算符中的裝箱和拆箱

public static void main(String[] args)
{
    Map<String,Boolean> map =  new HashMap<String, Boolean>();
    Boolean b = (map!=null ? map.get("test") : false);
}
  • jdk1.7編譯結(jié)果

    public static void main(String[] args) {
        HashMap map = new HashMap();
        Boolean b = Boolean.valueOf((boolean)(map != null ?((Boolean)map.get((Object)"test")).booleanValue() : false));
    }
    
    • 由于jdk1.7中捌议,第二和第三操作數(shù)為基本類型和對象時哼拔,會將對象拆箱,所有上述代碼執(zhí)行時會報空指針的錯誤瓣颅;
  • jdk1.8編譯結(jié)果

    public static void main(String[] args) {
        HashMap map = new HashMap();
        Boolean b = map != null ? (Boolean)map.get((Object)"test") : Boolean.valueOf((boolean)false);
    }
    
    • 理解要點

      • 三目運算符第二個和第三個操作數(shù)的類型不同時返回的類型到底是什么倦逐?
      • 第二個和第三個操作數(shù)會進(jìn)行什么操作?
    • 在java1.8中宫补,操作數(shù)共有18中檬姥,基本數(shù)據(jù)類型和對應(yīng)的包裝類共16個,加上null和Object共18個粉怕,所有表達(dá)式返回的數(shù)據(jù)類型組合共有324種情況健民。

    • lub()的理解

      least upper bound - basically the closest superclass that they have in common; since null (type "the special null type") can be implicitly converted (widened) to any type, you can consider the special null type to be a "superclass" of any type (class) for the purposes of lub().

      public static void main(String[] args)
      {
          Map<String,Boolean> map =  new HashMap<String, Boolean>();
          Boolean flag = true;
          Integer i = 1;
          Comparable res = map!=null ? flag : i;
          System.out.println(res);
      }
      

      如果第二個操作數(shù)是Boolean,第三個操作數(shù)是Integer贫贝,則三目運算符的返回類型是lub(Boolean,Integer)

      // 編譯后的結(jié)果
      public static void main(String[] args) {
          HashMap map = new HashMap();
          Boolean flag = Boolean.valueOf((boolean)true);
          Integer i = Integer.valueOf((int)1);
          Comparable res = (Comparable)(map != null ? (Comparable<Boolean>)flag : (Comparable<Boolean>)i);
          System.out.println((Object)res);
      }
      

      lub的作用是需找兩個對象的最小共同父類或者父接口荞雏,通過查看BooleanInteger代碼可以得到lub是Comparable接口

      public final class Boolean implements java.io.Serializable,
                                            Comparable<Boolean>{}
      
      public final class Integer extends Number implements Comparable<Integer> {}
      
    • bnp(..): bnp(..) means to apply binary numeric promotion.

      When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:

      1. If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
      2. Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
        • If either operand is of type double, the other is converted to double.
        • Otherwise, if either operand is of type float, the other is converted to float.
        • Otherwise, if either operand is of type long, the other is converted to long.
        • Otherwise, both operands are converted to type int.

      Binary numeric promotion is performed on the operands of certain operators:

    • T | bnp(..):The form "T | bnp(..)" is used where one operand is a constant expression of type intand may be representable in type T, where binary numeric promotion is used if the operand is not representable in type T.

      如果一個操作數(shù)是int的常量(即1,2,...,不是int變量)平酿,并且int常量的范圍在類型T的范圍內(nèi),則返回類型T悦陋,否則返回bnp(int,T)

      以第二個操作數(shù)為short蜈彼,第三個操作數(shù)為int為例,返回類型為short| bnp(short,int)俺驶,

      public static void main(String[] args)
      {
          // 以操作數(shù)二為short類型幸逆,操作三為int類型為例
          Map<String,Boolean> map =  new HashMap<String, Boolean>();
          short b1 = 1;
          int i1 = 2;
          short test = (map!=null ? b1 : 32767); // 編譯不報錯, short類型的范圍是[-32768,32767]暮现,所有32767可以轉(zhuǎn)化為short類型
          short test1 = (map!=null ? b1 : 32768); //編譯報錯还绘,32768不可以轉(zhuǎn)化為short類型
          short test2 = (map!=null ? b1 : i1); //編譯報錯,i1是符號引用栖袋,在編譯器無法確定具體的值拍顷,無法確定是否可以轉(zhuǎn)化為short類型。
      }
      
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末塘幅,一起剝皮案震驚了整個濱河市昔案,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌电媳,老刑警劉巖踏揣,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異匾乓,居然都是意外死亡捞稿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娱局,“玉大人彰亥,你說我怎么就攤上這事铃辖∈@ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵娇斩,是天一觀的道長仁卷。 經(jīng)常有香客問我,道長犬第,這世上最難降的妖魔是什么锦积? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮歉嗓,結(jié)果婚禮上丰介,老公的妹妹穿的比我還像新娘。我一直安慰自己鉴分,他們只是感情好哮幢,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著志珍,像睡著了一般橙垢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伦糯,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天柜某,我揣著相機與錄音,去河邊找鬼敛纲。 笑死喂击,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淤翔。 我是一名探鬼主播翰绊,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼旁壮!你這毒婦竟也來了辞做?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤寡具,失蹤者是張志新(化名)和其女友劉穎秤茅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體童叠,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡框喳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年课幕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片五垮。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡乍惊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出放仗,到底是詐尸還是另有隱情润绎,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布诞挨,位于F島的核電站莉撇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惶傻。R本人自食惡果不足惜棍郎,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望银室。 院中可真熱鬧涂佃,春花似錦、人聲如沸蜈敢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抓狭。三九已至伯病,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辐宾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工膨蛮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留叠纹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓敞葛,卻偏偏與公主長得像誉察,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子惹谐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 引入 == 基本數(shù)據(jù)類型(也稱原始數(shù)據(jù)類型) :byte,short,char,int,long,float,do...
    凱諾婷閱讀 1,202評論 1 7
  • 自動裝箱和拆箱從Java 1.5開始引入持偏,目的是將原始類型值轉(zhuǎn)自動地轉(zhuǎn)換成對應(yīng)的對象。自動裝箱與拆箱的機制可以讓我...
    codersm閱讀 418評論 0 0
  • 1氨肌、什么是裝箱鸿秆?什么是拆箱?Java為每種基本數(shù)據(jù)類型都提供了對應(yīng)的包裝器類型怎囚,在Java 1.5之前如果要生成一...
    高岳_bdf5閱讀 357評論 0 0
  • 今天去面試卿叽,負(fù)責(zé)人是朋友的朋友,一見面居然是一個課程的小組長。而且比我小3歲考婴。我有點蒙贩虾,這個世界是怎么了,我不過是...
    幸福女人成長閱讀 102評論 0 0
  • 這是我第一次使用簡書沥阱,我想記錄我的生活?今天我參加了我的寢室聚會缎罢,我的寢室6個人,人人都可以玩的來考杉,所以我們關(guān)系很...
    經(jīng)歷晨曦閱讀 207評論 0 0