常量缓存与integer比较_吊打面试官系列:说说Integer缓存范围

本文主要大致思路为:

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

案例

Integer是基本类型int的封装类。平时不管是入坑多年的小伙伴还在入坑路上的小伙伴,都应该知道的使用频率是相当高。

下面模仿订单支付,做了一个订单支付状态枚举类PayStatusEnumpublic 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 = 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)。

面试题

面试题1Integer num1 = new Integer(10);Integer num2 = new Integer(10);System.out.println(num1.equals(num2)); System.out.println(num1 == num2);

面试题2Integer num3 = 100;Integer num4 = 100;System.out.println(num3.equals(num4)); System.out.println(num3 == num4);

面试题3Integer 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中的使用缓存的方式也可以理解为享元模式。

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

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

相关文章

使用BIND安装智能DNS服务器(一)---基本的主从DNS服务器搭建

参考网址&#xff1a;http://www.unixmen.com/dns-server-installation-step-by-step-using-centos-6-3/   DNS(Domain Name System) 将主机名或者URLS翻译成IP地址。 例如&#xff1a;如果在浏览器输入网址 "www.unixmen.com" DNS server 将把这个域名翻译成和他…

openflow交换机 ryu_关于OpenFlow协议

SDN中两个重要元素&#xff1a;控制器(掌控全局&#xff0c;指挥网络内的设备工作)交换机(转发数据)控制器与网络设备通过OpenFlow协议进行通信OpenFlow交换机内有一个FlowTable&#xff0c;交换机按照流表转发数据&#xff0c;流表由控制器生成和维护。内有数据包匹配特征和数…

QT 语言切换

1. 代码里面需要切换语言的文字用tr包裹 2. 在工程pro文件目录下 3. 使用QT安装目录下的 Linguist程序增加中文字符串 4. 打开命令行 5. 执行 lrelease.exe ......\translations\zh_CN.ts

excel条形码字体_在Excel中批量生成条形码,竟如此简单!

条形码可以标出物品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等许多信息&#xff0c;因而在商品流通、图书管理、邮政管理、银行系统等许多领域都得到广泛的应用。那么如何在Excel中快速生成条形码呢&#xff1f;我们以前看到的方法有&am…

(视频) 《快速创建网站》 3.2 WordPress多站点及Azure在线代码编辑器 - 扔掉你的ftp工具吧,修改代码全部云端搞定...

本文是《快速创建网站》系列的第6篇&#xff0c;如果你还没有看过之前的内容&#xff0c;建议你点击以下目录中的章节先阅读其他内容再回到本文。 访问本系列目录&#xff0c;请点击&#xff1a;http://devopshub.cn/tag/wordpress-on-azure/ 1. 网站管理平台WordPress和云计算…

自定义外部协议使浏览器拉起本地程序

什么是自定义协议 由于我们的游戏需要在浏览器中调用NPAPI插件&#xff0c;而chrome移除了NPAPI的支持&#xff0c;导致游戏并不能很好的适配所有的浏览器&#xff0c;所以这个时候我们对于chrome浏览器用到了自定义浏览器协议这一标准。自定义浏览器协议允许在浏览器中使用pr…

hssfcolor 不建议使用_不建议使用微信双开的真正原因!

不少小伙伴都有两个甚至多个微信号&#xff0c;通常一个是自己的私人号&#xff0c;其它则用于工作&#xff0c;所以想要在手机中双开微信&#xff0c;这样使用起来更方便。不过使用 iPhone 的小伙伴就很郁闷了&#xff0c;为什么在 iPhone 上不能像部分安卓手机那样方便的双开…

【转】如何用css限制文字长度,使溢出的内容用省略号…显示

文章转自这里(现在貌似被黑了&#xff0c;建议不要点击了) ps&#xff1a;因在该地方没看到转载按钮&#xff0c;复制下存到这里以待自己方便&#xff0c;别人能看到帮助一下更是乐意之至&#xff0c;效果亲测可以实现&#xff0c;兼容IE、谷歌、火狐 由于文字内容长度的不确定…

yytextview多种格式_iOS YYText的使用笔记一(YYTextView图文编辑器)

YYText是强大的YYKit的一部分可以单独下载Powerful text framework for iOS to display and edit rich text. (Its a component ofYYKit)集成的时候建议使用cocopod管理1.里面主要两个控件&#xff1a;YYTextView 和 YYLabel现在主要是YYTextview的简单使用YYText主要是NSMutab…

React Canvas:高性能渲染 React 组

React Canvas 提供了使用 Canvas 渲染移动 Web App 界面的能力&#xff0c;替代传统的 DOM 渲染&#xff0c;具有更接近 Native App 的使用体验。React Canvas 提供了一组标准的 React 组件&#xff0c;由基于的渲染元素抽象而成。 GitHub 源码下载 示例代码&#xff1a; …

移除集合效率高还是add高_List、set集合接口分析

一、List接口详解1、List接口有三个实现类&#xff0c;ArrayList、LinkedList、Vector2、三个实现类的异同点&#xff1a;&#xff08;1&#xff09;ArrayList: 作为list接口的主要实现类&#xff1b;线程不安全&#xff0c;效率高&#xff1b;底层使用Object[]存储&#xff08…

代码实践

闭包举例&#xff1a; function closure(){var innerVariable inner;function innerFn(){ return innerVariable;}return innerFn(); } var innerVariable defined in outer; var outerVariable closure(); console.log(outerVariable); 测试字符串是否回文&#xff1a; …

python 读取excel太慢_Python 读取excel并转换为字典

方法一&#xff1a;利用利用xlrd读取excel文件其实整个过程比较简单&#xff0c;利用xlrd读取excel文件&#xff0c;再把读取到的数据转换为dict即可。1.安装 xlrdpip install xlrd2.读取文件&#xff0c;并进行格式转换导入的excel表格的格式是这样的&#xff1a;解析后的格式…

windows上编译zlib-1.2.8

MSVC编译 使用VS&#xff08;x86&#xff09;命令行工具进入到zlib根目录&#xff0c;执行 nmake -f win32/Makefile.msc ,在根目录下生成&#xff1a;zlib.lib(静态库) zdll.lib(动态库的导入库) zlib1.dll(动态库) 。必要的头文件有zlib.h和zconf.h 默认生成的是release版的…

大表与大表join数据倾斜_技术分享|大数据技术初探之Spark数据倾斜调优

侯亚南数据技术处支宸啸数据技术处在大数据计算中&#xff0c;我们可能会遇到一个很棘手的问题——数据倾斜&#xff0c;此时spark任务的性能会比预期要差很多&#xff1a;绝大多数task都很快执行完成&#xff0c;但个别task执行极慢或者报OOM(内存溢出)。数据倾斜调优&#xf…

NYOJ 289 苹果(01背包)

苹果 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述ctest有n个苹果&#xff0c;要将它放入容量为v的背包。给出第i个苹果的大小和价钱&#xff0c;求出能放入背包的苹果的总价钱最大值。 输入有多组测试数据&#xff0c;每组测试数据第一…

磁盘剩余空间策略_MySQL磁盘消耗迅猛掌握这点就够了,包你事半功倍

Part1:写在最前当一张单表10亿数据量的表放在你面前&#xff0c;你将面临着什么&#xff1f;Part2:背景介绍为了提升数据库资源利用率&#xff0c;一个实例中&#xff0c;在不互相影响&#xff0c;保证业务高效的前提下&#xff0c;我们会将同一个大业务下的不同小业务放在一个…

Date Picker控件:

Date Picker控件&#xff1a; 中文&#xff1a;日期/时间选取器UIDatePicker有一个实例方法setDate:animated&#xff0c;以编程的方式选择日期。UIDatePicker有四种模式&#xff08;model&#xff09;&#xff1a;Time&#xff08;只选时间&#xff09;Date&#xff08;只选日…

logback日志pattern_@Slf4j 实现日志输入到外部文件

添加一个配置文件\src\main\resources\logback-spring.xml<?xml version"1.0" encoding"UTF-8"?><configuration scan"true" scanPeriod"10 seconds"> <contextName>logbackcontextName> <prope…

C++ Prime:sizeof运算符

sizeof运算符的结果部分地依赖于其作用的类型&#xff1a; 对char或者类型为char的表达式执行sizeof运算结果得1&#xff1b; 对引用类型执行sizeof运算得到被引用对象所占空间的大小&#xff1b; 对指针执行sizeof运算得到指针本身所占空间的大小&#xff1b; 对解引用指针执行…