美文网首页
Kotlin 的装箱操作

Kotlin 的装箱操作

作者: JinYx | 来源:发表于2019-03-24 17:47 被阅读0次

      在看Kotlin的基本类型时,文档提到,Kotlin中所有东西都是对象;并且数字在 Java 平台是物理存储为 JVM 的原生类型,除非我们需要一个可空的引用(如 Int?)或泛型。 后者情况下会把数字装箱。
       刚看到数字装箱,猜测是不是类似Java中基本类型的包装类,int —> Integer... 然后例子中又提到一个数字装箱不一定保留同一性,判断的是两个数值的引用地址。如果是按照 Integer来装箱,boxedA 和 anotherBoxedA 应该是两个不同的 Integer对象,引用一定不同。


    图1. Kotlin装箱不一定保留同一性

       实践出真知,上代码

        fun testPacking() {
            val a: Int = 10000
            println(a === a) // 输出“true”
            val boxedA: Int? = a
            val anotherBoxedA: Int? = a
            println(boxedA === anotherBoxedA) // !!!输出“false”!!!
        }
    
        fun testPacking2() {
            val a: Int = 100
            println(a === a) // 输出“true”
            val boxedA: Int? = a
            val anotherBoxedA: Int? = a
            println(boxedA === anotherBoxedA) // !!!输出“true”!!!
        }
    

       上面的代码中,a的值不同,造成的结果也不同;查看一下Kotlin编译出的Java字节码,选中IDEA上面菜单栏的 Tools —> Kotlin —> Show Kotlin Bytecode,在打开的Kotlin Bytecode窗口中点击 Decompile


    图2. 查看Kotlin Bytecode

      上面代码编译成字节码后,对应的代码如下

       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 将数字进行了装箱操作,但是两个数值得到的值确实不一样的,查看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);
        }
    

    发现i的值在-128到127之间时,是从IntegerCache.cache中拿的,而不在该范围则是每次创建一个Integer对象

    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文档的示例代码中说的不一定保留同一性,表示的是数字范围在[-128, 127],引用相同,其他不同

    相关文章

      网友评论

          本文标题:Kotlin 的装箱操作

          本文链接:https://www.haomeiwen.com/subject/oxwuvqtx.html