Java自动装箱缓存机制

尝试运行这段代码:

相似的两段代码,得到的结果却完全不相同。

首先要知道在java中==比较的是对象的引用,从直觉出发,无论是integer1、integer2还是integer3、integer4都是不同的引用,结果都应该是不等的。

造成这个结果的原因是JDK1.5引入的包装类自动装箱时的缓存机制

自动装箱的概念:

Integer a = 10; //自动装箱,相当于下面这句
Integer a = Integer.valueOf(10);

而看看Integer中valueOf(int)的源码:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];//这句就是我们要研究的重点
    return new Integer(i);
}

IntegerCache是一个缓存类,它的内部有一个静态的Integer cache[]数组,在这个类第一次被加载时,会用整数值在-128~127之间的Integer实例对象填充这个数组,如果调用valueOf方法的时候参数值在这个范围内,就会从IntegerCache中的cache数组去取出这样一个共享对象。

这样就能回答一开始的程序integer1、integer2为什么相等了,因为他们都是从cache数组中取出来的同一个引用。

而300这个数是不在-128~127之间的,缓存数组中不存在这样的对象,最终是调用了构造方法创建了两个不同的Integer对象。


拓展:IntegerCache的静态代码块

static {
    // 缓存的数据范围可以由用户设置,这里从配置中获取了用户设置的缓存范围
    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;

    // 这里循环构造Integer对象填充cache数组
    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;
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/java%e8%87%aa%e5%8a%a8%e8%a3%85%e7%ae%b1%e7%bc%93%e5%ad%98%e6%9c%ba%e5%88%b6/

(0)
彭晨涛彭晨涛管理者
上一篇 2019年12月4日 18:05
下一篇 2019年12月6日

相关推荐

  • 按键排序的Map-TreeMap源码分析

    总结 总结放前面(这篇挺短的)1. TreeMap基于红黑树实现,可以对Map中的key排序2. 它的排序和定位需要依赖比较器或实现 Comparable 接口,也因此不需要key…

    Java 2020年2月16日
    0130
  • 深入理解java虚拟机第三版读书笔记03

    续深入理解java虚拟机第三版读书笔记02 HotSpot虚拟机对象探秘 对象的创建 当Java虚拟机遇到一条字节码new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一…

    2020年1月6日
    0120
  • Servlet4.0初识总结

    JavaEE8 JavaEE8,是自2013年6月Java企业版的首次更新。JAVAEE8提供了一些新的API,提供了对HTTP/2的新支持。 Servlet4.0 Servlet…

    Java 2019年11月28日
    02020
  • 日志门面SLF4J介绍和使用

    SLF4j概述 上篇文章写了日志门面介绍和JCL使用,作为一个曾经的主流日志门面技术,JCL终究因为设计时的产生问题所限,导致至今已没什么人使用,而一款优秀的日志门面技术SLF4j…

    2020年3月9日
    01330
  • 网络编程之AIO

    AIO介绍 AIO是JDK1.7引入的,也称为NIO 2.0 NIO的同步非阻塞类似于轮询,让Selector去询问各个通道的状态。 而AIO则是通过Future实现真正的异步,让…

    Java 2020年2月8日
    0280
  • 对象的输入输出-Java序列化机制

    对象序列化和反序列化,在Java中体现为两种字节流: ObjectInputStream、ObjectOutputStream 序列化的概念 指堆内存中的java对象数据,通过某种…

    Java 2019年12月21日
    0150
  • 深入理解java虚拟机第三版读书笔记13

    以下是第十三章 Java内存模型与线程的内容 线程安全 当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任…

    2020年1月30日
    0120
  • NIO底层原理-epoll

    BIO模型存在三个socket: ServerSocket:专门用来监听是否有来自客户端的连接accept返回的Socket:专门用于处理客户端请求的socketSocket:客户…

    Java 2020年2月13日
    0100
  • 操作系统五种IO模型介绍

    本文参考资源: 五种IO模型详解IO模型,java小范的博客-CSDN博客 阻塞 IO 模型 最传统的一种 IO 模型,即在读写数据过程中会发生阻塞现象。当用户线程发出 IO 请求…

    计算机相关 2020年2月12日
    0700
  • CopyOnWriteArrayList源码分析

    总结 总结放前面防止太长不看 CopyOnWriteArrayList是一个线程安全、并且在读操作时无锁的List实现。 CopyOnWriteArrayList内部通过volat…

    Java 2020年2月15日
    0180

发表回复

登录后才能评论