写点什么

可能一眼看不懂的几行 Kotlin 代码,程序员面试防坑宝典

用户头像
Android架构
关注
发布于: 15 小时前

同时我们在末尾再加上一段测试代码,采用直接new的方式构建对象,得到的比较结果为false


int c= 100;Integer cBox = new Integer(c);Integer cAnotherBox = new Integer(c);System.out.println(cBox == cAnotherBox); // false

原理

基础知识

  • Kotlin 中三等号(===) 比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间),双等号(==) 比较的是值;

  • Kotlin 中的非空 Number 类型对应到 JVM 平台是基本类型:int,double 等等;

  • Kotlin 中的可空 Number 类型对应到 JVM 平台是封装类型:Integer,Double 等等;

  • Java 中双等号(==)比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间);

  • Kotlin 中三等号等价于 Java 中的双等号;

字节码分析

val a: Int = 100


L0LINENUMBER 12 L0BIPUSH 100ISTORE 1


val boxedA: Int? = aval anotherBoxedA: Int? = a


L1LINENUMBER 13 L1ILOAD 1INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 2L2LINENUMBER 14 L2ILOAD 1INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;ASTORE 3


从字节码不难看出,非空 Int 型数据,直接使用BIPUSH压栈(取值 -128~127 时,JVM 采用 BIPUSH 指令将常量压栈)。而针对非空 Int 型变量赋值给可空 Int 型声明,是通过 Integer 类的 public static Integer valueOf(int i) 方法实现。


查看 Integer 类中 public static Integer valueOf(int i) 方法源码:


public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}


看到 IntegerCache 的一瞬间感觉一切都清晰了。JDK 从 1.5 版本开始,把 -128~127(high的默认值) 的数字缓存起来了,用于提升性能和节省内存,通过 -XX:AutoBoxCacheMax=<size> 来控制 high 的取值。所以,当数字在缓存范围内时,通过valueOf()方式拿到的对象引用全部来自于缓存列表,所以对于相同的值,对象引用相同;若是超过缓存范围,则是重新生成的对象,自然也就不相等了。此时回头看开头的两段 Kotlin 代码和我们改写的 Java 代码,就很清晰了。


/**


  • Cache to support the object identity semantics of autoboxing for values between

  • -128 and 127 (inclusive) as required by JLS.

  • The cache is initialized on first usage. The size of the cache

  • may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.

  • During VM initialization, java.lang.Integer.IntegerCache.high property

  • may be set and saved in the private system properties in the

  • sun.misc.VM class.*/


private static class IntegerCache {static final int low = -128;static final i


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


nt high;static final Integer cache[];


static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}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() {}}

IDEA 配置调整 high 值

通过配置-Djava.lang.Integer.IntegerCache.high=<size>或者-XX:AutoBoxCacheMax=<size>调整阈值。



延伸

除了 Integer类,CharacterByteShortLong 等类型也有类似的缓存,只是除了 Integer 外,其他类的缓存范围是不可变的。


private static class ByteCache {private ByteCache(){}


static final Byte cache[] = new Byte[-(-128) + 127 + 1];

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
可能一眼看不懂的几行Kotlin代码,程序员面试防坑宝典