Integer缓存机制

总结:

1、jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范围内值相等自动装箱返回的对象一样。jdk1.6后缓存范围的最大值127可以通过设置jvm的启动参数(-XX:AutoBoxCacheMax=size)调整
2、Integer的缓存只在自动装箱时有效,使用构造器(new)创建的对象不会触发缓存
3、int和Integer比较时不用考虑缓存问题,因为Integer会自动拆箱为int再和int比较,这时只是单纯的比较值是否相等

详解:
针对Integer常见的一个面试题为

Integer i1 = 100;
Integer i2 = 100;
Integer j1 = 200;
Integer j2 = 200;
System.out.println(i1 == i2); // 输出 true
System.out.println(j1 == j2); // 输出 false

我们对于Integer最基本的理解是Integer是int的包装类,是引用数据类型,引用数据类型用==比较的是对象的内存地址。
我们来看i1的创建过程(jdk1.8)
首先会对Integer i1 = 100;自动装箱(其实就是调用valueOf方法),java会把这段编译为Integer i1 = Integer.valueOf(100),可以自行查看class文件验证。
然后再看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);
}

可以清楚的看到是先从IntegerCache取值,IntegerCache.low IntegerCache.high 范围外则直接new对象(new的对象会存在堆内存中)

我们再来看IntegerCache类,IntegerCache为Integer的私有静态类

 /**
* 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 {@code -XX:AutoBoxCacheMax=<size>} 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.
*/ 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() {}
}

Integer的缓存通过for循环创建存放到一个数组中,注释已经解释该数组会在Integer第一次使用时初始化,结合类加载顺序来理解,第一次使用Integer时内部静态类会被初始化,静态代码块会被执行,存到堆中。会有第一次惩罚

jdk1.5源码参考

 private static class IntegerCache {
static final Integer[] cache = new Integer[256]; static {
for (int i = 0; i < cache.length; i++) {
cache[i] = new Integer(i - 128);
}
}
} public static Integer valueOf(int paramInt) {
if ((paramInt >= -128) && (paramInt <= 127)) {
return IntegerCache.cache[(paramInt + 128)];
}
return new Integer(paramInt);
}

Integer与int用==比较时Integer会自动拆箱(调用intValue()方法)为int进行比较
i1 == 100 会编译成 i1.intValue() == 100

其他缓存的对象
这种缓存行为不仅适用于Integer对象。我们针对所有整数类型的类都有类似的缓存机制。
有 ByteCache 用于缓存 Byte 对象
有 ShortCache 用于缓存 Short 对象
有 LongCache 用于缓存 Long 对象
有 CharacterCache 用于缓存 Character 对象
Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行。

参考博文:https://blog.csdn.net/qq_27093465/article/details/52473649

int与Integer(基本类型与包装类型)

Integer是int的包装类型,两者的区别为:

1、int初始值为0,Integer初始值为null,所有的引用类型都为null;

2、Integer为引用类型,对象存放在堆中。int为基本数据类型,对象存放在栈中;

使用包装类的好处:

1、Integer封装了很多处理方法,方便操作,比如进制转化(toBinaryString)、数据类型之间的转化(toString);

2、解决有些类型不支持基础数据类型的情况,比如List只能接收引用类型;

至于何时使用基本数据类型,何时使用包装类型这个就要看具体需求,当只是作为数值不需要更多的操作时用基本类型就可,灵活使用

基本数据类型和对应的包装类
int——Integer
float——Float 
double——Double 
byte——Byte
long——Long
char——Character
boolean——Boolean
short——Short

自动拆装箱(jdk1.5引入)

自动拆箱实际上就是引用类型自动转化成基本数据类型,自动装箱实际上就是基本数据类型自动转化成对应的引用类型

比如创建Integer i = new Integer(100); 可以直接写成Integer i = 100;不需要强转  (自动装箱)

int j = i  基本数据类型j可以直接等于引用类型i  (自动拆箱)

 Integer i = ;
int j = i; /**
* 上面代码编译成class后
*/
Integer i = Integer.valueOf();
int j = i.intValue();

由上可以看出自动装箱实际上就是调用了valueOf方法,自动拆箱调用了intValue方法

 

Integer缓存机制-基本数据类型和包装类型-自动拆装箱的更多相关文章

  1. Java基础(二) 基本类型数据类型、包装类及自动拆装箱

    我们知道基本数据类型包括byte, short, int, long, float, double, char, boolean,对应的包装类分别是Byte, Short, Integer, Long ...

  2. Java的自动拆装箱与Integer的缓存机制

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10832303.html 一:基本类型与包装类型     我们知道,Java有8大基本数据类型,4整2浮1符1 ...

  3. 自动拆装箱(int,Integer)

    包装类型Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个 ...

  4. Java基础进阶:APi使用,Math,Arrarys,Objects工具类,自动拆装箱,字符串与基本数据类型互转,递归算法源码,冒泡排序源码实现,快排实现源码,附重难点,代码实现源码,课堂笔记,课后扩展及答案

    要点摘要 Math: 类中么有构造方法,内部方法是静态的,可以直接类名.方式调用 常用: Math.abs(int a):返回参数绝对值 Math.ceil(double a):返回大于或等于参数的最 ...

  5. Java基本数据类型与包装类型(转)

    基本数据类型的包装类 为什么需要包装类? Java并不是纯面向对象的语言.Java语言是一个面向对象的语言,但是Java的基本数据类型却不是面向对象的.但是我们在实际使用中经常需要将基本数据转化成对象 ...

  6. Integer的缓存和自动拆装箱

    先看一个简单的例子: public class TestInteger { public static void main(String[] args) { System.out.println(&q ...

  7. java中的自动拆装箱与缓存(Java核心技术阅读笔记)

    最近在读<深入理解java核心技术>,对于里面比较重要的知识点做一个记录! 众所周知,Java是一个面向对象的语言,而java中的基本数据类型却不是面向对象的!为了解决这个问题,Java为 ...

  8. 《java入门第一季》之Integer类和自动拆装箱概述

    / * int 仅仅是一个基本类型.int有对应的类类型,那就是Integer.  * 为了对基本数据类型进行更多的操作,更方便的操作,Java就针对每一种基本数据类型提供了对应的类类型--包装类类型 ...

  9. java的数据类型、自动拆装箱、字面量

    java 中的数据类型分为两大类:值类型(基本数据类型)和引用类型(复合数据类型)  值类型分为 1,整数类型(byte,short,int,long) 2,浮点类型(float,double) 3, ...

随机推荐

  1. 在GeneXus开发过程中如何进行自动化测试?

    1. 简介 GXtest是基于专门为GeneXus平台开发的应用程序提供的自动化测试解决方案. 我们强调“解决方案”和“自动化”两个词: 解决方案:GXtest为整个GeneXus软件开发生命周期提供 ...

  2. how to render html tag

    使用autoescaping If autoescaping is turned on in the environment, all output will automatically be esc ...

  3. axios中请求传值方式

    日常开发中与后端联调,可能需要的数据不同,所传值也有所不同 1.如果是data方式,设置请求头为:并且直接返回data就可以  raw axios.defaults.headers['Content- ...

  4. wannafly camp day4

    2088: 电音之王 描述 题目描述: 终于活成了自己讨厌的样子. 听说多听电音能加快程序运行的速度. 定义一个数列,告诉你a0,a1,m0,m1,ca\_0,a\_1,m\_0,m\_1,ca0​, ...

  5. Linux.vim编辑器显示行号

    显示行号 :set number 取消显示行号:set nonumber

  6. ii

    char a[10], b[10], c[10], d[10],e[10],f[10],g[10],h[10]; scanf("%s %s %s %s", a, b, c, d); ...

  7. Collections.synchronizedList 、CopyOnWriteArrayList、Vector介绍、源码浅析与性能对比

    ## ArrayList线程安全问题 众所周知,`ArrayList`不是线程安全的,在并发场景使用`ArrayList`可能会导致add内容为null,迭代时并发修改list内容抛`Concurre ...

  8. linux开机无法进入桌面直接进入initramfs模式的问题修复

    可能是因为关机异常导致磁盘错误. kali linux升级到2019.4版本之后出现过好几次异常关机导致直接进入initramfs的模式,无法进入系统桌面,网上的办法基本上也都是无效的,前几次翻了很多 ...

  9. redis端口6379的由来

    有一个技巧,Redis端口号6379,是手机键盘上的MERZ.

  10. mysql--->mysql的事务和锁

    mysql 事务和锁 什么是事务?及其特性? 答:事务:是一系列的数据库操作,是数据库应用的基本逻辑单位. 或者这样理解: 事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操 ...