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日

相关推荐

  • 日志门面介绍和JCL使用

    日志门面概述 之前有写过Java日志框架JUL和Log4j介绍,可以对比发现它们之间的使用还是有一些区别的,比如有一些类名是不同的、日志的输出级别也不完全一致。 那么实际上是增大了…

  • Java网络套接字Socket编程

    Socket概述 Socket,译作网络套接字,是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。网络套接字与一个应用进程(ip和端口号)绑定。 Socket与Ser…

    Java 2020年2月5日
    0500
  • Java线程池详解

    线程池就是享元模式和生产者消费者模式的应用 动手实现线程池 步骤1:自定义拒绝策略接口 @FunctionalInterface // 拒绝策略 interface RejectP…

    2020年2月3日
    0320
  • JDK8-Stream流库详解

    流提供了一种让我们可以在比集合更高的概念级别上指定计算的数据视图。通过使用流,我们可以说明想要完成什么任务,而不是说明如何去实现它。 流的创建 Collection.stream(…

    Java 2020年2月11日
    0150
  • Java8避免空指针异常Optional类的使用

    最近都是一天写一篇算法题解,好久没有写过博客了,不知道写啥了而且快到期末考试了。。 今天介绍一个Java8的特性:Optional类,这个类我平时也不咋用,今天来研究一下。 Opt…

    Java 2020年6月3日
    0660
  • JavaIO-缓冲流与转换流

    缓冲流 概述 缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类: 字节缓冲流:BufferedInputStream,BufferedO…

    Java 2020年2月4日
    0130
  • JUC包下的信号量Semaphore

    概述 信号量,用来限制能同时访问共享资源的线程上限。 public static void main(String[] args) { // 1. 创建 semaphore 对象 …

    Java 2020年2月6日
    0200
  • IEEE754浮点数标准和舍入规则

    整理一下之前的笔记 浮点数与定点数 定点数 小数点在计算机中通常有两种表示方法,一种是约定所有数值数据的小数点隐含在某一个固定位置上,称为定点表示法,简称定点数。 其实整数也算是一…

    2020年4月2日
    01.3K0
  • LinkedHashMap源码分析

    总结 总结放前面防止太长不看: LinkedHashMap继承自HashMap,为Entry额外维护了两个属性:before和after,可以按照节点的插入顺序或者访问顺序为Ent…

    Java 2020年2月19日
    0550
  • 深入理解java虚拟机第三版读书笔记12

    以下是第十二章 Java内存模型与线程的内容 硬件的效率与一致性 基于高速缓存的存储交互很好地解决了处理器与内存速度之间的矛盾,但是也为计算机系统带来更高的复杂度,它引入了一个新的…

    2020年1月29日
    01540

发表回复

登录后才能评论