原文:https://www.cnblogs.com/JackPn/p/9392145.html

java有八个基本数据类型,每个都有对应的一个包装类,比如int对应的Integer。从jdk1.5开始,java引入了自动拆装箱,可以直接进行形如Integer i = 20形式的赋值,编译器会自动将其转换为Integer i = Integer.valueOf(20)进行装箱,拆箱则是将int j = i的形式转换成了int j = i.intValue()。

装箱有个细节,如果不注意很容易出错,来看一下:

Integer i = 20;
Integer j = Integer.valueOf(20); System.out.println(i == j);

上面的代码输出为

true

好像没什么问题,那我们形式不变,将数字20换成200,即

i = 200;
j = Integer.valueOf(200);
System.out.println(i == j);

同样的判断,输出变成了:

false

这是为什么呢?

先明确一点,经过编译器编译后,Integer i = 20转换成了Integer i = Integer.valueOf(20),和Integer j = Integer.valueOf(20)的定义完全一样,那为什么将20换成了200后判断结果不一样了呢?
我们来看看Integer.valueOf(int i)方法的内部:

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

可以看出当i在某个区间内时,直接返回了缓存数组IntegerCache.cache中的一个值,超出区间才new一个新的Integer对象。到这里我们大概就可以得出结论:20在缓存范围内所以直接用了缓存,但是200超出了缓存区间所以new了新对象,和原来对象的地址当然不会相同,所以返回false
再来看看IntegerCache,这是一个Integer的私有静态内部类,定义如下:

    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) {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low));
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
} private IntegerCache() {}
}

可以看出默认的缓存区间是-128~127,那么什么情况下会修改这个范围呢,修改了某个虚拟机参数的时候,通过代码也可看出,设置的这个缓存上限java.lang.Integer.IntegerCache.high值不能小于127,小于的话就会被赋予127,从而失效。
那么这个值怎么设置呢?我们来看看jdk源码中怎么解释IntegerCache这个静态内部类:

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 -XX:AutoBoxCacheMax= 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.

大概意思是:

将-128到127(包含)的数字做缓存以供自动装箱使用。缓存在第一次使用时被初始化。大小可以由JVM参数-xx:autoboxcachemax=option来指定。JVM初始化时此值被设置成java.lang.Integer.IntegerCache.high属性并作为私有的系统属性保存在sun.misc.vm.class中。

可以得到结论:这个缓存的high值是由JVM参数 -XX:AutoBoxCacheMax= option来指定的。

上述jdk源码来源于jdk1.7,不同版本实现略有不同,但思路一致。

这种共享常用对象的思路有一个名字,叫享元模式,英文名叫Flyweight,即共享的轻量级元素。其他包装类如Boolean、Byte、Short、Long、Charactor都有类似的实现。

java Integer包装类装箱的一个细节的更多相关文章

  1. Java SE之装箱与拆箱【基本数据类型的包装类/==与equals方法】

     对象包装器.自动装箱与拆箱   2016/11/30  晚   特点       1.所有的基本类型都有一个包装器类与之对应.[Integer,Boolean,Long,Character,Shor ...

  2. 再学Java 之 Integer 包装类缓存

    前言:本博文将涉及的Java的自动装箱和自动拆箱,可以参考 这篇文章 和 官方教程 ,这里不再赘述. 首先,先看一个小程序: public class Main { public static voi ...

  3. java基础(七)-----深入剖析Java中的装箱和拆箱

    本文主要介绍Java中的自动拆箱与自动装箱的有关知识. 基本数据类型 基本类型,或者叫做内置类型,是Java中不同于类(Class)的特殊类型.它们是我们编程中使用最频繁的类型. Java是一种强类型 ...

  4. Integer包装类源码分析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 今天上班的途中在手机里看到几道关于Integer拆装箱的小题目,正好有点时间翻看了一下Integer类的源码,加上自己的一点思考,决定写点 ...

  5. Java知识点梳理——装箱和拆箱

    1.前言:Java是典型的面向对象编程语言,但其中有8种基本数据类型不支持面向对象编程,基本数据类型不具备对象的特性,没有属性和方法:Java为此8种基本数据类型设计了对应的类(包装类),使之相互转换 ...

  6. Java的自动装箱/拆箱

    概述 自JDK1.5开始, 引入了自动装箱/拆箱这一语法糖, 它使程序员的代码变得更加简洁, 不再需要进行显式转换.基本类型与包装类型在某些操作符的作用下, 包装类型调用valueOf()方法将原始类 ...

  7. 小白学Java:包装类

    目录 小白学Java:包装类 包装类的继承关系 创建包装类实例 自动装箱与拆箱 自动装箱 自动拆箱 包装类型的比较 "=="比较 equals比较 自动装箱与拆箱引发的弊端 自动装 ...

  8. java自动拆装箱

    介绍 Java 5增加了自动装箱与自动拆箱机制,方便基本类型与包装类型的相互转换操作.(关于基本类型与包装类型之前有记录过https://www.cnblogs.com/xiuzhublog/p/12 ...

  9. Java:包装类小记

    Java:包装类 对 Java 中的 包装类 这个概念,做一个微不足道的小小小小记 基本数据&包装类 四类八种基本数据类型: 数据类型 关键字 内存占用 取值范围 字节型 byte 1个字节 ...

随机推荐

  1. java版云笔记(二)

    云笔记 基本的环境搭建好了,今天做些什么呢,第一是链接数据库(即搭建Spring-Batistas环境),第二是登录预注册. 注:这个项目的sql文件,需求文档,需要的html文件,jar包都可以去下 ...

  2. mysql 数据库备份及恢复

    1.备份 # 导出数据库:mysqldump -u 用户名 -p 数据库名 > 导出的文件名mysqldump -–add-drop-table -uusername -ppassword da ...

  3. ios测试apk

    最近apk在ios上面测试总是会遇到奇奇怪怪的问题,现在是两个项目要集成在一个apk中所以将两个项目运行之后都是编译成了.a文件,然后在两个.a文件中都设置了两个意义相同变量名相同的全局变量(标识当前 ...

  4. hexdump related.

    hexdump format strings Tue 13 December 2005 In tips. Ian Wienand More from the "things you'd le ...

  5. CentOS6.9下安装MariaDB10.2.11

    yum groupinstall -y "Development Tools" yum install -y cmake openssl-devel zlib-devel yum ...

  6. appium+python自动化39-adb shell输入中文(ADBKeyBoard)

    前言 上一篇提到"adb shell input textyoyo" 可以通过adb 输入英文的文本,由于不支持unicode编码,所以无法输入中文,github上有个国外的大神写 ...

  7. 两周撸一个掘金微信小程序

    利益相关 无 声明 这并不是掘金官方小程序(貌似没有搜到掘金 APP 对应的官方小程序),完全为第三者开发者开发,仅用于学习交流,禁止用于其他用途.若要使用官方正版,可访问掘金 官方网站,或下载掘金官 ...

  8. IEEEXtreme 10.0 - N-Palindromes

    这是 meelo 原创的 IEEEXtreme极限编程大赛题解 Xtreme 10.0 - N-Palindromes 题目来源 第10届IEEE极限编程大赛 https://www.hackerra ...

  9. vue引入自己写的js文件

    话不多说,直接上代码呀~ 先来个结构图: 中规中矩的vue-cli就写了一个自己的js文件 那么我想要引入到vue组件里. 1.首先写我的js文件 2.引入到vue组件!!!一定要用{}把方法名拿过来 ...

  10. lr11_Run-time Settings选项介绍:

    lr11_Run-time Settings选项介绍: ●Run Logic ●Pacing ●Log 下面对每个