自动装箱
自Java 1.5起,所有Java開發(fā)人員都可以使用自動(dòng)裝箱功能。嗯,我可能太樂觀了。 至少所有開發(fā)人員都應(yīng)該可以使用自動(dòng)裝箱。 畢竟,在ORACLE頁面上有一個(gè)很好的教程。
自動(dòng)裝箱是Java編譯器在需要時(shí)自動(dòng)從原始類型創(chuàng)建代碼創(chuàng)建對(duì)象的代碼時(shí)的現(xiàn)象。 例如,您可以編寫:
它將自動(dòng)生成將值int 42放入Integer對(duì)象的JVM代碼。 編譯器為我們做到這一點(diǎn)真是太好了,以至于一段時(shí)間后,程序員往往會(huì)忘記它背后的復(fù)雜性,而我們有時(shí)會(huì)碰壁。
例如,我們有double.class和Double.class 。 它們都是對(duì)象(作為一個(gè)類,每個(gè)類本身都是permgen中的對(duì)象,或者只是后permgen版本的JVM中的堆)。 這兩個(gè)對(duì)象都是Class類型。 而且,由于Java 1.5都屬于Class<Double>類型。
如果兩個(gè)對(duì)象具有相同的類型,那么它們也必須是賦值兼容的。 似乎是一個(gè)顯而易見的陳述。 如果您有對(duì)象O a和對(duì)象O b則可以指定a = b 。
查看代碼,但是我們可能會(huì)發(fā)現(xiàn)遺忘而不是顯而易見:
public class TypeFun {public static void main(String[] args) {// public static final Class<Double> TYPE = (Class<Double>)Class.getPrimitiveClass("double");System.out.println("Double.TYPE == double.class: " + (Double.TYPE == double.class));System.out.println("Double.TYPE == Double.class: " + (Double.TYPE == Double.class));System.out.println("double.class.isAssignableFrom(Double.class): " + (double.class.isAssignableFrom(Double.class)));System.out.println("Double.class.isAssignableFrom(double.class): " + (Double.class.isAssignableFrom(double.class)));} }結(jié)果:
Double.TYPE == double.class: true Double.TYPE == Double.class: false double.class.isAssignableFrom(Double.class): false Double.class.isAssignableFrom(double.class): false這意味著Double的原始對(duì)是double.class (不足為奇)。 即使不能從另一個(gè)分配一個(gè)。 我們至少可以查看其中之一的來源。 Double類的源代碼位于RT.jar中,并且是開源的。 在那里,您可以看到:
public static final Class<Double> TYPE = (Class<Double>) Class.getPrimitiveClass("double");為什么使用奇怪的Class.getPrimitiveClass("double")而不是double.class ? 那是Double類型的原始對(duì)。
答案并不簡(jiǎn)單,您可以深入研究Java和JVM的細(xì)節(jié)。 由于double不是一個(gè)類,因此實(shí)際上沒有比double.class了。 但是,您仍然可以在Java源代碼中使用此文字,并且Java語言,編譯器和運(yùn)行時(shí)具有很強(qiáng)的約束力。 編譯器知道Double類定義了一個(gè)名為TYPE的字段,該字段表示其原始類型。 每當(dāng)編譯器在源代碼中看到double.class ,它都會(huì)生成JVM代碼Double.TYPE (嘗試一下,然后使用javap解碼生成的代碼!)。 因此,RT的開發(fā)人員無法編寫:
public static final Class<Double> TYPE = double.class;進(jìn)入Double類的源代碼。 它將編譯為等效的代碼:
public static final Class<Double> TYPE = TYPE;那么自動(dòng)裝箱如何進(jìn)行? 來源:
Double b = (double)1.0;結(jié)果:
0: dconst_1 1: invokestatic #2 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;4: astore_1但是,如果我們替換兩個(gè)“ d”字母:
double b = (Double)1.0;然后我們得到:
0: dconst_1 1: invokestatic #2 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;4: invokevirtual #3 // Method java/lang/Double.doubleValue:()D7: dstore_1進(jìn)食可以解釋很多事情。 double.class類和Double.class類的實(shí)例不分配兼容。 自動(dòng)裝箱解決了這個(gè)問題。 Java 4很久以前了,幸運(yùn)的是,我們忘記了它。
您的作業(yè):重讀具有“類”類型和相應(yīng)原始類型參數(shù)的方法時(shí),重讀與自動(dòng)裝箱相關(guān)的事情。
翻譯自: https://www.javacodegeeks.com/2014/09/autoboxing.html
總結(jié)
- 上一篇: 如何使用单例EJB和MBean构建和清除
- 下一篇: jQuery Ajax – Servle