Kotlin 的裝箱操作

??在看Kotlin的基本類型時(shí),文檔提到,Kotlin中所有東西都是對(duì)象;并且數(shù)字在 Java 平臺(tái)是物理存儲(chǔ)為 JVM 的原生類型,除非我們需要一個(gè)可空的引用(如 Int?)或泛型。 后者情況下會(huì)把數(shù)字裝箱。
?? 剛看到數(shù)字裝箱,猜測(cè)是不是類似Java中基本類型的包裝類,int —> Integer... 然后例子中又提到一個(gè)數(shù)字裝箱不一定保留同一性,判斷的是兩個(gè)數(shù)值的引用地址。如果是按照 Integer來裝箱,boxedA 和 anotherBoxedA 應(yīng)該是兩個(gè)不同的 Integer對(duì)象,引用一定不同。


圖1. Kotlin裝箱不一定保留同一性

?? 實(shí)踐出真知,上代碼

    fun testPacking() {
        val a: Int = 10000
        println(a === a) // 輸出“true”
        val boxedA: Int? = a
        val anotherBoxedA: Int? = a
        println(boxedA === anotherBoxedA) // ?。。≥敵觥癴alse”?。?!
    }

    fun testPacking2() {
        val a: Int = 100
        println(a === a) // 輸出“true”
        val boxedA: Int? = a
        val anotherBoxedA: Int? = a
        println(boxedA === anotherBoxedA) // !??!輸出“true”?。?!
    }

?? 上面的代碼中,a的值不同,造成的結(jié)果也不同;查看一下Kotlin編譯出的Java字節(jié)碼,選中IDEA上面菜單欄的 Tools —> Kotlin —> Show Kotlin Bytecode,在打開的Kotlin Bytecode窗口中點(diǎn)擊 Decompile


圖2. 查看Kotlin Bytecode

??上面代碼編譯成字節(jié)碼后,對(duì)應(yīng)的代碼如下

   public final void testPacking() {
      int a = 10000;
      boolean var2 = true;
      System.out.println(var2);
      Integer boxedA = Integer.valueOf(a);
      Integer anotherBoxedA = Integer.valueOf(a);
      boolean var4 = boxedA == anotherBoxedA;
      System.out.println(var4);
   }

   public final void testPacking2() {
      int a = 100;
      boolean var2 = true;
      System.out.println(var2);
      Integer boxedA = Integer.valueOf(a);
      Integer anotherBoxedA = Integer.valueOf(a);
      boolean var4 = boxedA == anotherBoxedA;
      System.out.println(var4);
   }

??果不其然,是通過 Integer 將數(shù)字進(jìn)行了裝箱操作,但是兩個(gè)數(shù)值得到的值確實(shí)不一樣的,查看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);
    }

發(fā)現(xiàn)i的值在-128到127之間時(shí),是從IntegerCache.cache中拿的,而不在該范圍則是每次創(chuàng)建一個(gè)Integer對(duì)象

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

        static {
            // high value may be configured by property
            int h = 127;
            // 省略部分代碼......
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

所以Kotlin文檔的示例代碼中說的不一定保留同一性,表示的是數(shù)字范圍在[-128, 127],引用相同,其他不同

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

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

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