常量缓存与integer比较_Integer缓存范围到底是多少?

本文主要大致思路为:

c3871b7f04e4a095d1d9eae7539ca026.png

不管从工作中还是面试,这篇文章都应该好好看完,本人认为是非常有用的。

案例

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整体阅览

f8ea23abf520428cce559e8629567c0c.png

构造方法

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() {}

}

整个静态块流程:

9c72b417a48691816eb4e401acfedca5.png

那么,如何设置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

d12d61e14731083fabf9df475a3573e3.png

开始debug

d13ca9852c77b2e1b61326be185cdde0.png

看看high的值

760328a2f4fc29ff54e5d77ec7860fec.png

是127,那就对了,因为上面

b8f3be2650c7d630f2c4723c6d49439d.png

设置-XX:AutoBoxCacheMax=130

7a29d724c90725f5d031c8292ec50112.png

开启debug模式

dedc39c5b95cfbf9cc56ca535cab2e61.png

注意:low=-128是不会变的,整个缓存初始化过程并没有对low进行修改,再说low是常量。

-XX:AutoBoxCacheMax最大能设置成多大?

因为Integer的最大值是2147483647 ,所以我们这里使用这个值试试,

87f48e78fbe91a7feba73f836515929e.png

开始debug,直接报OOM了

a6e6ea864383a28a3f2797a774051627.png

为什么会OOM呢?

7ba7ce1905536785199eb0a0e33b09ed.png

如果-XX:AutoBoxCacheMax没有设置值,那么对应数组是这样的。

e34165d4510371e08dd94d2be12f5028.png

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文件中的字节码;

本地变量表

d8eeb299b5627763c9f369d5591def44.png

每个本地变量赋值的过程

cc9fb1e15eef9db0040e6cc507ec196c.png

这里我们可以得出一个结论:

Integer c =8;就是Integer c = Integer.valueOf(8);

上面Integer b = Integer.valueOf(8);,那就说明变量b和c都是使用Integer.valueOf()获取到的。

valueOf方法中

32bbb285eed9fd0775645d66e6b5b01d.png

-XX:AutoBoxCacheMax不设置

上面关于IntegerCache的low和high已经进行了说明,low永远是-128,所以当我们没有设置

-XX:AutoBoxCacheMax 的值的时候,这时候 high=127。

当Integer.valueOf(8);的时候,就会进入上面代码中的if中。然后从IntegerCache中的数组cache中获取。

但是IntegerCache中的cache数组是个常量数组。

551d863b42f8070f1edacc21dc3b66b6.png

言外之意,就是一旦给这个数组cache赋值后,就不会变了。

Integer b = Integer.valueOf(8);和Integer c=8;

b和c不就是都指向同一个引用地址吗?

所以 b==c为true;

dac4ed619d4fecf2378ba3eb8344de96.png

但是Integer b=Integer.valueOf(128);

此时就不进入if中,而是直接new一个Integer对象

ebbfdfb4fdabf3a205439bb6322bb133.png

所以此时

Integer b=Innteger.valueOf(128) ;和Integer c = 128;

都会各自new 一个Integer对象,

此时的b==c为false。

b5e8b413955d3050c086b2f0093dcdae.png

这里也就是网上很多文章也就说到这里,就是比较当前int i 这个i是不是在-128到127范围之内。

-XX:AutoBoxCacheMax设置为130

如果我们把-XX:AutoBoxCacheMax设置为130。那么上面

Integer b=Innteger.valueOf(128) ;和Integer c = 128;

也会进入if条件中。

最后b==c为true。

5b26fd5b79bb8dee83c7ac30c1afa8f2.png

如何避坑

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后端技术全栈

a9de4416dfe14f664078f0460257c415.png

专业做Java相关技术分享的的公众号。一个纯粹的Java技术分享达人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

supervisor 子进程退出_用supervisor监管你的程序,不用担心程序挂了

1.背景无论多么优秀的程序员都难以避免写出来的程序会有崩溃的一天&#xff0c;特别是c、c这种高技术含量的语言&#xff0c;一不小心就来个段错误&#xff08;segment fault&#xff09;,我们通常会写一个守护进程或者守护脚本&#xff0c;检测对应的进程是否退出&#xff0c;…

pta7-3 统计不及格人数_应用统计专硕院校专业难度分析【青岛大学、苏大、西安交通大学】...

原文链接&#xff1a;应用统计专硕院校专业难度分析【第十二期】​mp.weixin.qq.com应用统计专硕院校专业难度分析 【第十二期】TO&#xff1a;哈喽&#xff0c;小可爱们早上给你好呀&#xff01;今天安安姐给你们更新经济类6个专硕院校专业难度分析专题第十二期&#xff0c;大…

mysql数据库事务有几种特性_面试官:你能说说事务的几个特性是啥?有哪几种隔离级别?...

1、面试题事务的几个特点是什么&#xff1f;数据库事务有哪些隔离级别&#xff1f;MySQL的默认隔离级别&#xff1f;2、面试官心里分析用mysql开发的三个基本面&#xff1a;存储引擎、索引&#xff0c;然后就是事务&#xff0c;你必须得用事务。因为一个业务系统里&#xff0c;…

latex 图片大小_用LaTeX写作业——插入图片(二)

&#xfeff;方法 subfigure可以横向排列一组图片&#xff0c;会自动编号abcd。在一个 subfigure内使用minipage插入图片&#xff0c;通过控制图片大小实现换行效果 # 效果 代码usepackage{subfigure} %所需宏包 usepackage{graphicx}begin{figure}[htbp] centersubfigure[标题…

python中单例模式是什么_python中的单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式&#xff0c;该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中&#xff0c;某个类只能出现一个实例时&#xff0c;单例对象就能派上用场。比如&#xff0c;某个服务器程序的配置信息存放在一个文件中…

java rsa算法_求RSA算法JAVA实现源代码(带界面的)

展开全部import javax.crypto.Cipher;import java.security.*;import java.security.spec.RSAPublicKeySpec;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.InvalidKeySpecException;import java.security.interfaces.RSAPrivateKey;import java.sec…

java string值传递_String是值传递还是引用传递

string中的坑最近看到一道关于string的面试题&#xff0c;差点让我以为string是值传递&#xff0c;就是下面这个例子&#xff0c;体验下&#xff1a;public class demo{public static void main(string[] args) {demo d new demo();string str "bea";d.change(str)…

java切换jdk版本_切换JDK版本quick

最近遇到一个小问题&#xff0c;同时做两个项目&#xff0c;jdk版本一个是5&#xff0c;一个是6&#xff0c;我也去网上找了找方法&#xff0c;但是感觉不是特别好用&#xff0c;最后自己通过一些环境变量设置的技巧和一些批处理命令来使得这件事情只需要双击&#xff0c;输入一…

Linux下导出MySQL为SQL文件_MySQL导入导出.sql文件步骤

MySQL导入导出.sql文件步骤如下&#xff1a;一.MySQL的命令行模式的设置&#xff1a;桌面->我的电脑->属性->环境变量->新建->PATH“&#xff1b;path\mysql\bin;”其中path为MySQL的安装路径。二.简单的介绍一下命令行进入MySQL的方法&#xff1a;1.C:\>mys…

java 对象视图框架_Stripes视图框架Java对象属性验证和prototype.js Ajax的测试

Stripes视图框架Java对象属性验证&#xff0c;它允许对字段设置是否必须填写&#xff0c;对数字大小进行限制等。我用prototype.js Ajax 将验证后的数据及时地展示出来&#xff0c;下面来看程序。1、编写User实体类此用户共三个属性&#xff1a; name、email、age.package com.…

java中unicode显示乱码_Java 已知Java系统编码是GBK,jtextarea从一编码为Unicode的文本中读取数据,出现乱码,怎么正常显示?...

Java 已知Java系统编码是GBK&#xff0c;jtextarea从一编码为Unicode的文本中读取数据&#xff0c;出现乱码&#xff0c;怎么正常显示&#xff1f;关注:159 答案:2 mip版解决时间 2021-02-03 12:45提问者鉨瞞着所囿亾&#xff0c;爱着誰2021-02-02 16:35我觉得jtextarea中读取…

php怎么seo,怎样学习seo

学习seo的方法&#xff1a;1、从搜索引擎原理开始&#xff0c;学习seo要先从搜索引擎原理开始&#xff1b;2、多思考&#xff1b;3、学习seo要多看高质量的seo教程&#xff1b;4、多和seo高手交流&#xff0c;经常听听大神的seo理论&#xff0c;集百家之所长&#xff0c;这样会…

php ip 短时间 重复,php 限制同一个IP 一段时间不能评论多次,能给我详细解决的...

php 限制同一个IP 一段时间不能评论多次,能给我详细解决的mip版 关注:163 答案:3 悬赏:30解决时间 2021-01-25 15:27已解决2021-01-25 05:54php 限制同一个IP 一段时间不能评论多次,能给我详细解决的最佳答案2021-01-25 06:49在评论的操作中&#xff0c;都需要记录用户ip地址…

java 8 list,JAVA8 ListListInteger list中再装一个list转成一个list操作

我就废话不多说了&#xff0c;大家还是直接看代码吧~List collect IntStream.range(1, 10).boxed().collect(Collectors.toList());List collect1 IntStream.range(10, 20).boxed().collect(Collectors.toList());List> lists new ArrayList<>();lists.add(collect…

matlab中创建一个工程,从文件夹创建新工程

从文件夹创建新工程如果您有许多文件并希望将它们整理为一个工程(无论是否进行源代码管理)&#xff0c;请按照以下步骤创建一个新工程。使用 Simulink Start Page 中的 Folder to Project 模板可轻松将一个文件夹转换为工程。该模板会自动将您的文件添加到工程中&#xff0c;并…

Java定义变量x初始值为3,JAVA 第一章

第一章1.注释&#xff1a;一个好的开发习惯&#xff0c;应该是多编写注释&#xff0c;这样程序的可读性增强。单行注释// 单行注释 &#xff0c;只注释当前行多行注释/*多行注释多行注释*/javadoc 注释/**javadoc 注释javadoc 注释javadoc 注释*/注意&#xff1a;这种注释是比较…

血型算法php,血型排行榜!(真的很准)

一最容易动怒的人是&#xff1a;1.O 型&#xff1a;急性子&#xff0c;一点小事就能惹火他&#xff0c;性格中有好斗的一面&#xff0c;会以 " 我想发泄一下 " 为理由大发雷霆。2.B 型&#xff1a;看上去脾气很好&#xff0c;其实性情很直接&#xff0c;被愤怒冲昏头…

每个java小应用程序都得继承,JAVA复习题3

23.容器JFrame及JPanel默认的布局管理器分别是()A、FlowLayout和GridLayoutB、BorderLayout和FlowLayoutC、FlowLayout和FlowLayoutD、CardLayout和BorderLayout24.在开发一个JAVA GUI程序时&#xff0c;通常都要对按键事件作出响应和处理&#xff0c;一般需要在程序的开头写上…

anaconda下安装python,Windows下Anaconda的安装和简单使用方法

Anaconda is a completely free Python distribution (including for commercial use and redistribution). It includes over 195 of the most popular Python packagesfor science, math, engineering, data analysis.1、安装anaconda之前什么都不需要安装&#xff0c;直接在…

oracle免费云攻略,使用免费的Oracle云服务-创建云主机

上一篇我们讲了如何注册并使用Oracle的免费云服务&#xff0c;这篇我们讲如何创建免费的云主机。进入到控制台后&#xff0c;从左上角的菜单栏进入到Instances的管理界面&#xff1a;然后点击&#xff0c;则会进入创建云主机的界面。创建云主机真的非常简单&#xff0c;甚至你都…