常量缓存与integer比较_Integer缓存范围到底是多少?
本文主要大致思路为:
不管从工作中还是面试,这篇文章都应该好好看完,本人认为是非常有用的。
案例
Integer是基本类型int的封装类。平时不管是入坑多年的小伙伴还在入坑路上的小伙伴,都应该知道的使用频率是相当高。
下面模仿订单支付,做了一个订单支付状态枚举类PayStatusEnum
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(8);
Integer b = Integer.valueOf(8);
Integer c = 8;
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
System.out.println(a == b);
System.out.println(a == c);
System.out.println(b == c);
}
}
结果输出什么?
把上面代码中的8改成128后,又输出什么?
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(128);
Integer b = Integer.valueOf(128);
Integer c = 128;
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
System.out.println(a == b);
System.out.println(a == c);
System.out.println(b == c);
}
}
答案慢慢道来。
解析案例
Integer整体阅览
构造方法
private final int value;
public Integer(int value) {
this.value = value;
}
太简单了,没什么可讲的。
valueOf()方法
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
//@HotSpotIntrinsicCandidate 这个注解是JDK9才引入的
//HotSpot 虚拟机将对标注了@HotSpotIntrinsicCandidate注解的方法的调用,
//替换为直接使用基于特定 CPU 指令的高效实现。这些方法我们便称之为 intrinsic。
public static Integer valueOf(int i) {
//如果i在low和high之间就使用缓存
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
上面valueOf()方法中用到了IntegerCache,下面我们来聊聊。
IntegerCache
下面是IntegerCache源码和部分注释:
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
* JLS协议要求缓存在-128到127之间(包含边界值)
*
* The cache is initialized on first usage.
* 程序第一次使用Integer的时候
* The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
* JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改最大值
* 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.
* 可以通过系统属性来获得:-Djava.lang.Integer.IntegerCache.high=
*/
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");
//如果有配置-XX:AutoBoxCacheMax=
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
//和127进行比较,谁大用谁
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.
// 如果该值配置错误则忽略该参数配置的值,使用默认范围-128~127
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
// 缓存通过for循环来实现,创建范围内的整数对象并存储到cache数组中
// 程序第一次使用Integer的时候需要一定的额外时间来初始化该缓存
for(int k = 0; k < cache.length; k++){
cache[k] = new Integer(j++);
}
//无论如何,缓存的最大值肯定是大于等于127
assert IntegerCache.high >= 127;
}
//私有的构造方法,因为所有的属性均属于类常量
private IntegerCache() {}
}
整个静态块流程:
那么,如何设置java.lang.Integer.IntegerCache.high的值呢?
The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
注释中已经说清楚,可以使用-XX:AutoBoxCacheMax=设置。
写个demo来debug看看
public class IntegerDemo {
public static void main(String[] args) {
Integer a = 8;
Integer b =Integer.valueOf(8);
System.out.println(a.equals(b));
System.out.println(a == b);
}
}
设置-XX:AutoBoxCacheMax=100
开始debug
看看high的值
是127,那就对了,因为上面
设置-XX:AutoBoxCacheMax=130
开启debug模式
注意:low=-128是不会变的,整个缓存初始化过程并没有对low进行修改,再说low是常量。
-XX:AutoBoxCacheMax最大能设置成多大?
因为Integer的最大值是2147483647 ,所以我们这里使用这个值试试,
开始debug,直接报OOM了
为什么会OOM呢?
如果-XX:AutoBoxCacheMax没有设置值,那么对应数组是这样的。
equals()方法
上面的案例中有equals方法,这里把这个方法也拿出来聊聊
private final int value;
public boolean equals(Object obj) {
if (obj instanceof Integer) {
//这里比较的是两个int类型的值
return value == ((Integer)obj).intValue();
}
//obj不是Integer类型直接返回false
return false;
}
回到上面的案例中
当我们使用equals方法比较两个对象是否相等的时候其实就是比较他们的value值。
所以不管是128还是8,equals后肯定都是true。
当引用类型使用==进行比较的时候,此时比较的是两个引用的对象的地址,是不是同一个。
public class IntegerDemo {
public static void main(String[] args) {
Integer a = new Integer(8);
Integer b = Integer.valueOf(8);
Integer c = 8;
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
System.out.println(a == b);
System.out.println(a == c);
System.out.println(b == c);
}
}
我们看看器class文件中的字节码;
本地变量表
每个本地变量赋值的过程
这里我们可以得出一个结论:
Integer c =8;就是Integer c = Integer.valueOf(8);
上面Integer b = Integer.valueOf(8);,那就说明变量b和c都是使用Integer.valueOf()获取到的。
valueOf方法中
-XX:AutoBoxCacheMax不设置
上面关于IntegerCache的low和high已经进行了说明,low永远是-128,所以当我们没有设置
-XX:AutoBoxCacheMax 的值的时候,这时候 high=127。
当Integer.valueOf(8);的时候,就会进入上面代码中的if中。然后从IntegerCache中的数组cache中获取。
但是IntegerCache中的cache数组是个常量数组。
言外之意,就是一旦给这个数组cache赋值后,就不会变了。
Integer b = Integer.valueOf(8);和Integer c=8;
b和c不就是都指向同一个引用地址吗?
所以 b==c为true;
但是Integer b=Integer.valueOf(128);
此时就不进入if中,而是直接new一个Integer对象
所以此时
Integer b=Innteger.valueOf(128) ;和Integer c = 128;
都会各自new 一个Integer对象,
此时的b==c为false。
这里也就是网上很多文章也就说到这里,就是比较当前int i 这个i是不是在-128到127范围之内。
-XX:AutoBoxCacheMax设置为130
如果我们把-XX:AutoBoxCacheMax设置为130。那么上面
Integer b=Innteger.valueOf(128) ;和Integer c = 128;
也会进入if条件中。
最后b==c为true。
如何避坑
Integer是基本类型int的封装类,那么在平常使用的时候需要注意几点:
1,如果使用Integer,注意Integer的默认是null,容易引起空指针异常NullPointerException。
2,如果使用int类型,注意int类型的初始值是0,很多设计某某状态时,很喜欢用0作为某个状态,这里要小心使用。
3,另外从内存使用层面来讲,int是基本数据类型,只占用4个字节,Integer是一个对象,当表示一个值时Integer占用的内存空间要高于int类型,从节省内存空间考虑,建议使用int类型(建议了解一下Java对象内存布局)。
4,Integer使用的时候,直接赋值,Integer c = 8,不要new Integer(8)。因为直接赋值就是Integer.valueOf方法使用缓存,没必要每次都new一个新对象,有效提高内存使用。
5,如果系统中大量重复的使用比127大的数,建议JVM启动的时候为-XX:AutoBoxCacheMax=size 适当的大小,提升内存使用效率(但是也不能太大,上面我们已经演示了可能出现OOM)。
面试题
面试题1
Integer num1 = new Integer(10);
Integer num2 = new Integer(10);
System.out.println(num1.equals(num2));
System.out.println(num1 == num2);
面试题2
Integer num3 = 100;
Integer num4 = 100;
System.out.println(num3.equals(num4));
System.out.println(num3 == num4);
面试题3
Integer num5 = 1000;
Integer num6 = 1000;
System.out.println(num5.equals(num6));
System.out.println(num5 == num6);
把上面看完了,在回头来看看这种面试题,还难吗?
如果在面试中遇到面试题3,可以适当反问一下面试官是否有对缓存范围进行调整,或许某些面试官都会懵逼。
赤裸裸的吊打面试官。
总结
1.引用类型的==是比较对应的引用地址。
2.Integer中使用的默认缓存是-128到127。但是可以在JVM启动的时候进行设置。
3.Integer b=Integer.valueOf(8);和Integer b=8;是一样的效果。
4.Integer.valueOf()方式,比较是否在缓存范围之内,在就直接从缓存中获取,不在new一个Integer对象。
5.每次使用new来创建Integer对象,是用不到IntegerCache缓存的。
6.Integer中的使用缓存的方式也可以理解为享元模式。
欢迎关注我的公众号:java后端技术全栈
专业做Java相关技术分享的的公众号。一个纯粹的Java技术分享达人。
常量缓存与integer比较_Integer缓存范围到底是多少?相关推荐
- 常量缓存与integer比较_Integer和int使用==进行比较大小时的坑
先看一个例子: public static void main(String[] args) { int i1 = 128; Integer i2 = 128; Integer i3 = new In ...
- Java整数缓存-为什么Integer.valueOf(127)== Integer.valueOf(127)为True
在一次采访中,我的一个朋友被问到如果我们有两个Integer对象, Integer a = 127; Integer b = 127; Integer a = 127; Integer b = 127 ...
- Java经典面试题—— int 和 Integer 有什么区别?谈谈 Integer 的值缓存范围
典型回答 int 是我们常说的整型数字,是 Java 的 8 个原始数据类型(PrimitiveTypes,boolean.char.byte.short.int.long.float 和 doubl ...
- int 和 Integer 有什么区别,Integer的值缓存范围
目录 int与Integer的基本使用对比 int与Integer的深入对比 int与Integer的基本使用对比 Integer是int的包装类:int是基本数据类型: Integer变量必须实例化 ...
- Integer的自动缓存
2019独角兽企业重金招聘Python工程师标准>>> Interger装箱有个自动缓存的概念 Integer a = 100;Integer b = 100;Integer c = ...
- Hibernate缓存原理与策略 Hibernate缓存原理:
Hibernate缓存原理: 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等 ...
- 两难!先更新数据库再删缓存?还是先删缓存再更新数据库?
前言 当我们在做数据库与缓存数据同步时,究竟更新缓存,还是删除缓存,究竟是先操作数据库,还是先操作缓存?本文带大家深度分析数据库与缓存的双写问题,并且给出了所有方案的实现代码方便大家参考. 本篇文章主 ...
- java实现lru缓存_Java中的LRU缓存实现
java实现lru缓存 什么是LRU缓存? (What is LRU Cache?) LRU Cache stands for Least Recently Used Cache. The size ...
- REDIS13_缓存雪崩、缓存穿透、基于布隆过滤器解决缓存穿透的问题、缓存击穿、基于缓存击穿工作实际案例
文章目录 ①. 缓存雪崩 ②. 缓存穿透 ③. 在centos7下布隆过滤器2种安装方式 ④. 缓存击穿 ⑤. 高并发的淘宝聚划算案例落地 ①. 缓存雪崩 ①. 问题的产生:缓存雪崩是指缓存数据大批量 ...
最新文章
- python 面向对象(云储存一下)
- php csv文件的读取,写入,输出下载操作详解
- redis的string类型和bitmap
- springcloud(七)-Feign声明式REST调用
- 获取页面所有属性并生成html6,JavaScript基础练习题(三)
- 【C语言编程】实现猜数字游戏
- OpenStack温哥华峰会Day2日记:大数据带你看峰会热点
- win10pe命令打开计算机,Win10是怎么进入安全模式
- 章鱼网络应用链|为什么 DEIP 会选择章鱼网络?
- Manjaro安装与软件硬件基本配置(保姆级)
- Android 启动页白屏 快速解决
- 【PPic】项目中重要第三方组件集成打包测试
- Gitlab两个项目代码合并
- 从今日起,做一个有归置的男人!
- 计算机风筝设计图片教程,如何利用塑料袋制作风筝图解教程
- mysql 计算近30天总金额_计算月嫂每天工资,应该用总工资除以30天还是26天?-免费法律咨询...
- 安装惠普打印机显示等待php,HP打印机安装过程中报错0x000006be的解决方法
- nyoj 1238 最少换乘(spfa)
- 开源网络风云变幻,看各家爱恨情仇
- orangepi——i2c协议,0led显示
热门文章
- MFC新建文件夹、打开文件夹的实现方法
- git+pylint实现python提交代码格式校验
- Mapreduce的排序、全排序以及二次排序
- Linux(CentOS 7)安装docker
- python socket udp_python网络-Socket之udp编程(24)
- uniapp 可视化开发_uniapp的简单安装流程使用教程
- ::在sql语句中是什么写法_不懂就问:SQL 语句中 where 条件后 写上1=1 是什么意思...
- 11210怎么等于24_想要消耗100大卡热量,怎么做才最简单?
- activex for chrome扩展程序 下载”_Chrome扩展程序一键生成网页骨架屏
- win7系统5分钟自动注销的解决方法