Java中的裝箱和拆箱深刻懂得。本站提示廣大學習愛好者:(Java中的裝箱和拆箱深刻懂得)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中的裝箱和拆箱深刻懂得正文
主動裝箱和拆箱成績是Java中一個陳詞濫調的成績了,明天我們就來一些看一下裝箱和拆箱中的若干成績。本文先講述裝箱和拆箱最根本的器械,再來看一上面試口試中常常碰到的與裝箱、拆箱相干的成績。
一.甚麼是裝箱?甚麼是拆箱?
在後面的文章中提到,Java為每種根本數據類型都供給了對應的包裝器類型,至於為何會為每種根本數據類型供給包裝器類型在此不停止論述,有興致的同伙可以查閱相干材料。在Java SE5之前,假如要生成一個數值為10的Integer對象,必需如許停止:
Integer i = new Integer(10);
而在從Java SE5開端就供給了主動裝箱的特征,假如要生成一個數值為10的Integer對象,只須要如許便可以了:
Integer i = 10;
這個進程中會主動依據數值創立對應的 Integer對象,這就是裝箱。
那甚麼是拆箱呢?望文生義,跟裝箱對應,就是主動將包裝器類型轉換為根本數據類型:
Integer i = 10; //裝箱
int n = i; //拆箱
簡略一點說,裝箱就是 主動將根本數據類型轉換為包裝器類型;拆箱就是 主動將包裝器類型轉換為根本數據類型。
下表是根本數據類型對應的包裝器類型:
二.裝箱和拆箱是若何完成的
上一末節懂得裝箱的根本概念以後,這一末節來懂得一下裝箱和拆箱是若何完成的。
我們就以Interger類為例,上面看一段代碼:
public class Main { public static void main(String[] args) { Integer i = 10; int n = i; } }
反編譯class文件以後獲得以下內容:
從反編譯獲得的字節碼內容可以看出,在裝箱的時刻主動挪用的是Integer的valueOf(int)辦法。而在拆箱的時刻主動挪用的是Integer的intValue辦法。
其他的也相似,好比Double、Character,不信任的同伙可以本身手動測驗考試一下。
是以可以用一句話總結裝箱和拆箱的完成進程:
裝箱進程是經由過程挪用包裝器的valueOf辦法完成的,而拆箱進程是經由過程挪用包裝器的 xxxValue辦法完成的。(xxx代表對應的根本數據類型)。
三.面試中相干的成績
固然年夜多半人對裝箱和拆箱的概念都清晰,然則在面試和口試中碰到了與裝箱和拆箱的成績卻紛歧定會答得下去。上面羅列一些罕見的與裝箱/拆箱有關的面試題。
1.上面這段代碼的輸入成果是甚麼?
public class Main { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); System.out.println(i3==i4); } }
或許有些同伙會說都邑輸入false,或許也有同伙會說都邑輸入true。然則現實上輸入成果是:
true
false
為何會湧現如許的成果?輸入成果注解i1和i2指向的是統一個對象,而i3和i4指向的是分歧的對象。此時只需一看源碼便知畢竟,上面這段代碼是Integer的valueOf辦法的詳細完成:
public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }
而個中IntegerCache類的完成為:
private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
從這2段代碼可以看出,在經由過程valueOf辦法創立Integer對象的時刻,假如數值在[-128,127]之間,便前往指向IntegerCache.cache中曾經存在的對象的援用;不然創立一個新的Integer對象。
下面的代碼中i1和i2的數值為100,是以會直接從cache中取曾經存在的對象,所以i1和i2指向的是統一個對象,而i3和i4則是分離指向分歧的對象。
2.上面這段代碼的輸入成果是甚麼?
public class Main { public static void main(String[] args) { Double i1 = 100.0; Double i2 = 100.0; Double i3 = 200.0; Double i4 = 200.0; System.out.println(i1==i2); System.out.println(i3==i4); } }
或許有的同伙會以為跟下面一道標題的輸入成果雷同,然則現實上卻不是。現實輸入成果為:
false
false
至於詳細為何,讀者可以去檢查Double類的valueOf的完成。
在這裡只說明一下為何Double類的valueOf辦法會采取與Integer類的valueOf辦法分歧的完成。很簡略:在某個規模內的整型數值的個數是無限的,而浮點數卻不是。
留意,Integer、Short、Byte、Character、Long這幾個類的valueOf辦法的完成是相似的。
Double、Float的valueOf辦法的完成是相似的。
3.上面這段代碼輸入成果是甚麼:
public class Main { public static void main(String[] args) { Boolean i1 = false; Boolean i2 = false; Boolean i3 = true; Boolean i4 = true; System.out.println(i1==i2); System.out.println(i3==i4); } }
輸入成果是:
true
true
至於為何是這個成果,異樣地,看了Boolean類的源碼也會了如指掌。上面是Boolean的valueOf辦法的詳細完成:
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
而個中的 TRUE 和FALSE又是甚麼呢?在Boolean中界說了2個靜態成員屬性:
public static final Boolean TRUE = new Boolean(true); /** * The <code>Boolean</code> object corresponding to the primitive * value <code>false</code>. */ public static final Boolean FALSE = new Boolean(false);
至此,年夜家應當明確了為什麼下面輸入的成果都是true了。
4.談談Integer i = new Integer(xxx)和Integer i =xxx;這兩種方法的差別。
固然,這個標題屬於比擬廣泛類型的。然則要點必定要答上,我總結一下重要有以下這兩點差別:
1)第一種方法不會觸發主動裝箱的進程;而第二種方法會觸發;
2)在履行效力和資本占用上的差別。第二種方法的履行效力和資本占用在普通性格況下要優於第一種情形(留意這其實不是相對的)。
5.上面法式的輸入成果是甚麼?
public class Main { 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; Long h = 2L; 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)); System.out.println(g.equals(a+h)); } }
先別看輸入成果,讀者本身想一下這段代碼的輸入成果是甚麼。這外面須要留意的是:當 “==”運算符的兩個操作數都是 包裝器類型的援用,則是比擬指向的能否是統一個對象,而假如個中有一個操作數是表達式(即包括算術運算)則比擬的是數值(即會觸發主動拆箱的進程)。別的,關於包裝器類型,equals辦法其實不會停止類型轉換。明確了這2點以後,下面的輸入成果便了如指掌:
true
false
true
true
true
false
true
第一個和第二個輸入成果沒有甚麼疑問。第三句因為 a+b包括了算術運算,是以會觸發主動拆箱進程(會挪用intValue辦法),是以它們比擬的是數值能否相等。而關於c.equals(a+b)會先觸發主動拆箱進程,再觸發主動裝箱進程,也就是說a+b,會先各自挪用intValue辦法,獲得了加法運算後的數值以後,便挪用Integer.valueOf辦法,再停止equals比擬。同理關於前面的也是如許,不外要留意倒數第二個和最初一個輸入的成果(假如數值是int類型的,裝箱進程挪用的是Integer.valueOf;假如是long類型的,裝箱挪用的Long.valueOf辦法)。
以上所述是小編給年夜家引見的Java中的裝箱和拆箱深刻懂得,願望對年夜家有所贊助,假如年夜家有任何疑問請給我留言,小編會實時答復年夜家的。在此也異常感激年夜家對網站的支撐!