• Java 自动拆箱 装箱 包装类的缓存问题--结合源码分析


    都0202 了 java 1.8 已经是主流
    自动装箱 、拆箱已经很普遍使用了,那么有时候是不是会遇到坑呢?

    我们先来看一段代码:

    public class TestWraperClass {
    	public static void main(String[] args) {
    		Integer a = 200;
    		Integer b = 200;
    		
    		Integer c = 123;
    		Integer d = 123;
    		
    		System.out.println(a == b);
    		System.out.println(c == d);
    	}
    }
    

    运行结果:
    在这里插入图片描述

    代码中 a==b 结果为false 容易理解,毕竟是两个不同对象;
    那么 c == d 为什么结果会是 true 呢?

    其实在程序编译时,编辑器会给我们的代码加上 Integer.valueOf(int i)。
    即上面的代码相当于:

    Integer a = Integer.valueOf(200);
    Integer b = Integer.valueOf(200);
    
    Integer c = Integer.valueOf(123);
    Integer d = Integer.valueOf(123);
    

    我们可以按住CTRL键鼠标点击valueOf 查看JDK源码有这么一段代码:

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

    也就是说,当给 Integer.valueOf(int i) 出入的参数在某个范围内是,会直接从一个数组中取值

    我可以继续按住CTRL键鼠标点击 cache 进入 IntegerCache 类,我们可以看到源码如下:

     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;
                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_VALUE
                        h = 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() {}
        }
    

    看关键代码:
    在这里插入图片描述
    很明显可以看到 IntegerCache.cache[i + (-IntegerCache.low)] 其实就是一个 从-128 到 127 的 静态初始化 Integer 数组 ,当我们调用时,已经存在java 虚拟机的堆中了,不需要重新创建。

    那么回到最开始的代码:
    当我们创Integer 对象的值在[-127, 128] 范围时,其实取的都是 cache[] 数组的同一个对象。
    至此,已经可以很好结算 开始代码的运行结果了。

    重视基础,才能走的更远。
  • 相关阅读:
    【整理】互联网服务端技术体系:存储基础之数据存储与索引结构
    python基础之enumerate() 函数+ Counter类计数器
    介绍几个好用的Java库
    【GIS】BlenderGIS应用配置之一
    使任意同步库快速变asyncio异步语法的方式 ,run_in_executor
    mysql查看表行数
    mysql8.0使用mysqldump报错:Unknown table ‘column_statistics‘ in information_schema (1109)
    sysbench安装使用,结果信息分析
    【1.6】shell使用 -p -f 之类的参数
    右键新建项中添加Typora新建Markdown文件快捷选项
  • 原文地址:https://www.cnblogs.com/xzlf/p/12681548.html
Copyright © 2020-2023  润新知