前言

一切从下面这段代码开始

public static void test(String[] agrs){
    Integer a = 1;
    Integer b = 2;
    System.out.println("a=" + a + ", b=" + b);
    swap( a, b );
    System.out.println("a=" + a + ", b=" + b);
}

public static void swap( Integer a, Integer b ){
    // 实现它
}

过程

因为Java中的方法只有值传递,所以无法使用下面的方式来完成交换。

public static void swap( Integer a, Integer b ){
    Integer tmp = a;
    a = b;
    b = tmp;
}

因为Integer没有提供直接修改值的方法,所以能想到的就是用反射机制去修改Integer对象持有的值。于是就有了下面的代码

public static void swap( Integer a, Integer b ){
    try {
        Integer tmp = new Integer(a);
        Field fieldA = a.getClass().getDeclaredField("value");
        fieldA.setAccessible(true);
        fieldA.set(a, b);

        Field fieldB = b.getClass().getDeclaredField("value");
        fieldB.setAccessible(true);
        fieldB.set(b, tmp);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

执行后发现ab引用对象的值确实交换了。

但是在main()的最后加上这段代码,会发现输出是c=2!!

Integer c = 1;
System.out.println("c=" + c);

Integer缓存

查看字节码可以发现Integer a = 1;实际是通过Integer.valueOf()获取的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在[IntegerCache.low,IntegerCache.high]区间内时,总是返回cache中的对象引用。

low不可配置,默认为-128;high可配置,默认为127。

由此就可以知道,因为ab引用的是cache中的对象,swap()后,cache中对象的值和其在数组中的下标已经不对应了,所以c引用的对象的实际值是2。

为了避免交换影响到Integer的缓存,我们必须使用new来实例化ab引用的对象。

结语

Java似乎就是有意不让程序员去修改对象内存的,只能改改引用的对象,像String的替换、追加等操作,都是返回一个新实例化的对象,而不是在原对象的内存中修改。

Java学习点滴——Integer缓存的更多相关文章

  1. Java学习点滴——初识Java

    基于<Java编程思想>第四版 前言 "程序就是算法加数据结构",而算法就是控制语句加操作符,编写一个程序就是使用控制语句加操作符去操作数据结构,因此我从Java的控制 ...

  2. java封装数据类型——Integer 缓存策略验证

    上一篇学习 Integer 类型源码,知道了它使用缓存策略,默认对 [-128, 127] 范围的对象进行类加载时自动创建缓存. Integer 源码学习:https://www.cnblogs.co ...

  3. Java学习点滴——泛型

    基于<Java编程思想>第四版 前言 虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的. 语法 Java只需要一个<>就可定义泛型.在<> ...

  4. Java学习点滴——Class和反射

    基于<Java编程思想>第四版 前言 我们要操作一个类实例对象时,一般都要先知道这个类有哪些方法或者成员变量.反射就是在我们不知道这个类有哪些方法或成员变量时,使用特定方式得到类的这些信息 ...

  5. java学习-Comparable<Integer>接口方法的实现

    基本数据类型的包装类Integer, Float, Double,Long,Byte等都实现的Comparable接口,用于列表List或数组arrays的排序 Comparable<Integ ...

  6. Java学习点滴——对象实例化

    基于<Java编程思想>第四版 构造与析构 在C++中通过构造函数和析构函数来保证:对象在使用前被正确初始化,在使用后被正确回收.Java中同样存在构造函数,但是没有析构函数.之所以没有析 ...

  7. 从.Net到Java学习第七篇——SpringBoot Redis 缓存穿透

    从.Net到Java学习系列目录 场景描述:我们在项目中使用缓存通常都是先检查缓存中是否存在,如果存在直接返回缓存内容,如果不存在就直接查询数据库然后再缓存查询结果返回.这个时候如果我们查询的某一个数 ...

  8. java中字面量,常量和变量之间的区别(附:Integer缓存机制)

    一.引子 在各种教科书和博客中这三者经常被引用,今天复习到内存区域,想起常量池中就是存着字面量和符号引用,其实这三者并不是只在java中才有,各个语言中都有类似的定义,所以做一下总结,以示区分. 二. ...

  9. Java常量池详解之Integer缓存

    一个Java question,求输出结果   public class IntegerTest { public static void main(String[] args) { objPoolT ...

随机推荐

  1. .Net开发者必知的技术类RSS订阅指南

    目录 RSS订阅资源 .Net基金会 MSDN中文版 杂志 微软 Github 系列 微软DevBlog系列 InfoQ中文版系列 如何找到大佬的 Twitter/Youtube/Stackoverf ...

  2. HttpServletRequest 接口、HttpServletResponse 接口、请求转发与重定向

    上篇文章我们讲了servlet的基本原理,这章将讲一下剩余的部分. HttpServletRequest 接口 该接口是 ServletRequest 接口的子接口,封装了 HTTP 请求的相关信息, ...

  3. 整合X-Admin前端框架改造ABP

    “站在巨人的肩膀上”,这样一来,不要万事亲恭,在值得的方向上节约时间,毕竟人生就这么一次.在接触ABP以来,一直想花点时间整合LayUI前端框架到ABP中,进而能够逐渐打磨出一套适合自己的框架,开发习 ...

  4. Java异常处理最佳实践及陷阱防范

    前言 不管在我们的工作还是生活中,总会出现各种“错误”,各种突发的“异常”.无论我们做了多少准备,多少测试,这些异常总会在某个时间点出现,如果处理不当或是不及时,往往还会导致其他新的问题出现.所以我们 ...

  5. Android Gradle 依赖配置:implementation & api

    背景: Android Gradle plugin 3.0开始(对应Gradle版本 4.1及以上),原有的依赖配置类型compile已经被废弃,开始使用implementation.api和anno ...

  6. Java虚拟机三:OutOfMemoryError异常分析

    根据Java虚拟机规范,虚拟机内存中除过程序计数器之外的运行时数据区域都会发生OutOfMemoryError(OOM),本文将通过实际例子验证分析各个数据区域OOM的情况.为了更贴近生产,本次所有例 ...

  7. 用系统为centos6的主机,搭建PXE服务器,实现批量安装centos6,7系统

    1. iptables -F setenforce 0 临时关掉selinux,清掉防火墙 永久生效更改配置文件:vim /etc/sysconfig/selinux chkconfig iptabl ...

  8. jQuery AJAX与jQuery事件的分析讲解

    jQuery 本身即是为事件处理而特别设计的,jQuery 事件处理方法是 jQuery 中的核心函数. $(function() { ... }); 是如下格式的缩写: ? 1 $(document ...

  9. Intellij idea 离线安装activiti工作流插件

    想在Intellij idea上安装一个activiti插件玩玩,由于网络环境原因,不能使用网上已有的在线搜索acti bpm并安装的方式.也在网上找了好久没找到离线安装的方式.自己摸索了一下装好了, ...

  10. Spark初步 从wordcount开始

    Spark初步-从wordcount开始 spark中自带的example,有一个wordcount例子,我们逐步分析wordcount代码,开始我们的spark之旅. 准备工作 把README.md ...