摘要:學(xué)過(guò)的同學(xué)或多或少都聽(tīng)過(guò)自動(dòng)裝箱拆箱下邊通過(guò)代碼和字節(jié)碼文件加深下對(duì)自動(dòng)拆箱裝箱的理解為什么要有包裝類(lèi)型作為和基本數(shù)據(jù)類(lèi)型對(duì)應(yīng)的類(lèi)類(lèi)型存在,方便涉及到對(duì)象的操作比如泛型必須要求我們是對(duì)象數(shù)據(jù)類(lèi)型自動(dòng)裝箱拆箱發(fā)生在什么時(shí)候自動(dòng)拆箱裝箱發(fā)生在代
學(xué)過(guò)Java的同學(xué)或多或少都聽(tīng)過(guò)自動(dòng)裝箱拆箱,下邊通過(guò)代碼和字節(jié)碼文件加深下對(duì)自動(dòng)拆箱裝箱的理解.
1為什么要有包裝類(lèi)型?作為和基本數(shù)據(jù)類(lèi)型對(duì)應(yīng)的類(lèi)類(lèi)型存在,方便涉及到對(duì)象的操作,比如泛型必須要求我們是對(duì)象數(shù)據(jù)類(lèi)型.
2 自動(dòng)裝箱拆箱發(fā)生在什么時(shí)候?自動(dòng)拆箱裝箱發(fā)生在代碼編譯期間.
通過(guò)例子來(lái)看下自動(dòng)拆箱裝箱是怎么做的:
public static void main(String[] args) { Long a = 100L; Long b = 100L; long c = 100L; Long d = new Long(100); Long e = 1000L; Long f = 1000L; System.out.println(a == b); System.out.println(a == c); System.out.println(a == d); System.out.println(c == d); System.out.println(e == f); }
下面先公布答案:
true
true
false
true
false
蒙 a==b為true; 為什么 e==f就是false? a和c是怎么比較的? a和d又是什么情況?
接下來(lái)我們通過(guò)字節(jié)碼文件看看到底有什么奧秘:
public static void main(java.lang.String[]); Code: 0: ldc2_w #2 // long 100l 3: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 6: astore_1 7: ldc2_w #2 // long 100l 10: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 13: astore_2 14: ldc2_w #2 // long 100l 17: lstore_3 18: new #5 // class java/lang/Long 21: dup 22: ldc2_w #2 // long 100l 25: invokespecial #6 // Method java/lang/Long."":(J)V 28: astore 5 30: ldc2_w #7 // long 1000l 33: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 36: astore 6 38: ldc2_w #7 // long 1000l 41: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long; 44: astore 7 46: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 49: aload_1 50: aload_2 51: if_acmpne 58 54: iconst_1 55: goto 59 58: iconst_0 59: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V 62: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 65: aload_1 66: invokevirtual #11 // Method java/lang/Long.longValue:()J 69: lload_3 70: lcmp 71: ifne 78 74: iconst_1 75: goto 79 78: iconst_0 79: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V 82: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 85: aload_1 86: aload 5 88: if_acmpne 95 91: iconst_1 92: goto 96 95: iconst_0 96: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V 99: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 102: lload_3 103: aload 5 105: invokevirtual #11 // Method java/lang/Long.longValue:()J 108: lcmp 109: ifne 116 112: iconst_1 113: goto 117 116: iconst_0 117: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V 120: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 123: aload 6 125: aload 7 127: if_acmpne 134 130: iconst_1 131: goto 135 134: iconst_0 135: invokevirtual #10 // Method java/io/PrintStream.println:(Z)V 138: return }
鬼畫(huà)符?我們看下這些鬼到底什么意思.
3: invokestatic #4 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
意思是執(zhí)行 Long 的valueof()方法 參數(shù)為基本類(lèi)型 返回值為L(zhǎng)ong類(lèi)型
看看Long的valueof方法
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
如果傳入的基本類(lèi)型在-128-127之內(nèi)就,就從LongCache中取數(shù)據(jù)返回給我們.看下LongCache干了啥
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } }
原來(lái)如此,-128-127就直接返回給我們chche中的數(shù)據(jù),超出這個(gè)范圍直接new一個(gè)給我們.a==b為true,e==f為false就說(shuō)得通了.
65: aload_1 66: invokevirtual #11 // Method java/lang/Long.longValue:()J 69: lload_3 70: lcmp
拿出變量a,執(zhí)行Long.longValue()返回一個(gè)基本數(shù)據(jù)類(lèi)型,在和c比較.看下longValue方法
/** * Returns the value of this {@code Long} as a * {@code long} value. */ public long longValue() { return value; }
這部就是兩個(gè)基本數(shù)據(jù)類(lèi)型比較嗎.
85: aload_1 86: aload 5 88: if_acmpne 95
取出a和d直接比較內(nèi)存地址是否一樣.鐵定不一樣呀.
剩下的大家可以自己看下,有不明白的可以評(píng)論問(wèn).
3 總結(jié)自動(dòng)拆箱裝箱沒(méi)有什么神秘的.字節(jié)碼可以告訴我們很東西.如果某些概念理解不了,試著看看字節(jié)碼文件.說(shuō)不定會(huì)豁然開(kāi)朗.
如果發(fā)現(xiàn)文章中有不妥之處,希望大家指出,共同進(jìn)步.
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/75983.html
摘要:本章部分內(nèi)容從源碼中解讀一些自動(dòng)裝箱與拆箱的原理,以及會(huì)出現(xiàn)的一些陷阱已經(jīng)性能等。例題分析我們通過(guò)幾個(gè)經(jīng)典的問(wèn)題,來(lái)看看大家到底理解了裝箱與拆箱的知識(shí)點(diǎn)沒(méi)。 showImg(https://img-blog.csdnimg.cn/20190426221838971.gif);showImg(https://img-blog.csdnimg.cn/20190426221918208.pn...
摘要:對(duì)象頭的另外一部分是類(lèi)型指針,即對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例。并不是所有的虛擬機(jī)實(shí)現(xiàn)都必須在對(duì)象數(shù)據(jù)上保留類(lèi)型指針,換句話(huà)說(shuō),查找對(duì)象的元數(shù)據(jù)信息并不一定要經(jīng)過(guò)對(duì)象本身,這點(diǎn)將在節(jié)討論。 目錄介紹 1.關(guān)于int和Integer的問(wèn)題區(qū)別分析 2.Integer的值緩存的原理 2.1 Java 5 中引入緩存特性 2.2 Intege...
摘要:作為條件變量的的不僅可以認(rèn)為內(nèi)嵌了一把鎖,還內(nèi)嵌了一個(gè)條件變量。操作條件變量的函數(shù)將當(dāng)前線(xiàn)程在條件變量上阻塞,一般是為了等待其他線(xiàn)程的某件事情執(zhí)行完成。其它裝箱類(lèi)其它裝箱類(lèi)的代碼這里就不分析了。重點(diǎn)關(guān)注下各裝箱類(lèi)的緩存范圍。 jdk源碼讀到現(xiàn)在這里,重要的集合類(lèi)也讀了一部分了。集合類(lèi)再往下讀的話(huà),就要涉及到兩個(gè)方向。第一,是比較典型的但是不常用的數(shù)據(jù)結(jié)構(gòu),這部分我準(zhǔn)備將數(shù)據(jù)結(jié)構(gòu)復(fù)習(xí)、回...
摘要:文章主要介紹通過(guò)改進(jìn)就已存在的骨灰級(jí)特性大幅度提高應(yīng)用性能。在繼續(xù)解釋造成差異的細(xì)節(jié)之前,讓我們仔細(xì)回味一下中的這兩個(gè)概念自動(dòng)裝箱與拆箱。 【編者按】本文作者為 Ali Kemal TASCI,最早于2016年4月9日發(fā)布于DZONE社區(qū)。文章主要介紹通過(guò)改進(jìn) Java 1.5 就已存在的骨灰級(jí)特性大幅度提高應(yīng)用性能。 本文系 OneAPM 工程師編譯呈現(xiàn),以下為正文。 如果我告訴你:...
摘要:前陣子,我們分享了中的基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換這篇文章,對(duì)許多粉絲還是有帶來(lái)幫助的,今天講一下包裝類(lèi)的的由來(lái),及自動(dòng)裝箱拆箱的概念和原理。下面是基本數(shù)據(jù)類(lèi)型與對(duì)應(yīng)的包裝類(lèi)型。 showImg(https://segmentfault.com/img/remote/1460000016537706); 前陣子,我們分享了《Java中的基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換》這篇文章,對(duì)許多粉絲還是有帶來(lái)幫助的,今天講...
閱讀 3755·2023-04-26 02:32
閱讀 4251·2021-11-23 10:05
閱讀 2381·2021-10-08 10:04
閱讀 2881·2021-09-22 16:06
閱讀 3699·2021-09-22 15:27
閱讀 830·2019-08-30 15:54
閱讀 1865·2019-08-30 13:50
閱讀 2778·2019-08-29 13:56