Hold住面试官之Integer Cache

前言

最近跟许多朋友聊了下,在这个“跳槽”的黄金季节,大家都有点蠢蠢欲动,所以最近就多聊聊面试的时候需要注意的一些问题,这些问题不一定多深奥,多复杂,但是一不注意的话却容易掉坑。下面看一下面试的时候经常遇到的一段代码:

1public class IntegerDemo { 2 public static void main(String[] args) { 3 Integer numA = 127; 4 Integer numB = 127; 5 6 Integer numC = 128; 7 Integer numD = 128; 8 9 System.out.println("numA == numB : "+ (numA == numB)); 10 System.out.println("numC == numD : "+ (numC == numD)); 11 } 12}

根据大家以往的经验,会认为上面的代码用“==“符号来比较,对比的是对象的引用,那么ABCD是不同的对象,所以输出当然是false了。我在《“==”、“equals()”、“hashcode()”之间的秘密》这篇文章也讨论过。那么事实也是如此吗?下面看一下输出结果:

1numA == numB : true 2numC == numD : false

What?这个输出结果怎么跟以往的认知有所出入呢?在我们的代码“Integer numA = 127”中,编译器会把基本数据的“自动装箱”(autoboxing)成包装类,所以这行代码就等价于“Integer numA = Integer.valueOf(127)”了,这样我们就可以进入valueOf方法查看它的实现原理。

1//Integer valueOf方法 2public static Integer valueOf(int i) { 3if (i >= IntegerCache.low && i <= IntegerCache.high) 4 return IntegerCache.cache[i + (-IntegerCache.low)]; 5 return new Integer(i); 6} 7 8//Integer静态内部类 9private static class IntegerCache { 10 static final int low = -128; 11 static final int high; 12 static final Integer cache[]; 13 14 static { 15 // high value may be configured by property 16 int h = 127; 17 String integerCacheHighPropValue = 18 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 19 if (integerCacheHighPropValue != null) { 20 try { 21 int i = parseInt(integerCacheHighPropValue); 22 i = Math.max(i, 127); 23 // Maximum array size is Integer.MAX_VALUE 24 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 25 } catch( NumberFormatException nfe) { 26 // If the property cannot be parsed into an int, ignore it. 27 } 28 } 29 high = h; 30 cache = new Integer[(high - low) + 1]; 31 int j = low; 32 for(int k = 0; k < cache.length; k++) 33 cache[k] = new Integer(j++); 34 35 // range [-128, 127] must be interned (JLS7 5.1.7) 36 assert IntegerCache.high >= 127; 37 } 38 39 private IntegerCache() {} 40 }

从上面的源码可以看到,valueOf方法会先判断传进来的参数是否在IntegerCache的low与high之间,如果是的话就返回cache数组里面的缓存值,不是的话就new Integer(i)返回。

那我们再往上看一下IntegerCache,它是Integer的内部静态类,low默认是-128,high的值默认127,但是high可以通过JVM启动参数XX:AutoBoxCacheMax=size来修改(如图),如果我们按照这样修改了,然后再次执行上面代码,这时候2次输出都是true,因为缓存的区间变成-128~200了。

但是如果我们是通过构造器来生成一个Integer对象的话,下面的输出都是false。因为这样不会走ValueOf方法,所以按照正常的对象对比逻辑即可。

1public class IntegerDemo { 2 public static void main(String[] args) { 3 Integer numA = new Integer(127); 4 Integer numB = new Integer(127); 5 6 Integer numC = new Integer(128); 7 Integer numD = new Integer(128); 8 9 System.out.println("numA == numB : "+ (numA == numB));//false 10 System.out.println("numC == numD : "+ (numC == numD));//false 11 } 12}

还有需要注意的一点是,此类缓存行为不仅存在于Integer对象。还存在于其他的整数类型Byte,Short,Long,Character。但是能改变缓存范围的就只有Integer了。

结语

有时候往往越简单的知识越容易掉坑里,所以要保持自己的求知欲,不断巩固的基础,才能让自己在面试的时候不会栽跟头。

喜欢的话~关注一下微信公众号《深夜里的程序猿》,每天分享最干的干货


文章推荐

Redis的正确使用姿势

一文彻底搞懂面试中常问的各种“锁”

那些年我们一起踩过的Dubbo坑

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Redis发布订阅:最简单最通俗的文章

前言可能小伙伴的工作年限大部分已经超过三年甚至四年五年,不知道是否有一种危机感,我们写了那么多的需求代码没有20w行也有个10w行了吧,但是出去找工作的时候不是笔试被pass掉就是面试被pass,你会发现好多你只是知道但是回答不上来。这个时候你才知道去补习知识点,其实这种做法对自身发展不太友好的。我去年疫情期间,在大家都不敢跳槽季节我义无反顾选择跳槽,进入大

百度后端二面有哪些内容,万字总结(一)

前言这是最近一位老朋友去百度面试,应该是面试资深工程师岗位,他跟我讲被问到mysql索引知识点?其实面试官主要还是考察对mysql的性能调优相关,问理论知识其实也是想知道你对原理的认知,从而确认你是否有相关的调优经验。朋友说他回答的还行,然后很顺利进行了三面四面。那么本文将跟大家一起来聊一聊这个如何回答面试官的这个问题!公众号:我是阿沐以下是自己的理解

运维大佬嘲笑我,这个你都不知道?

大家好,我是阿沐,一个喜欢分享技术而且爱好写散文的程序员。今天来给大家介绍一下info命令查看redis具体的详细信息讲解!起因是:前几年我在老家郑州实习面试(那个时候还没有毕业)的时候遇到面试官提问;面试官来于百度总部的工程师6年java开发经验3年多的PHP开发经验,我在他的面前基本就是弟弟中的弟弟,虽然勉强通过入职了,但是却被运维无情地嘲笑,就因为组

Java面试集锦

各位学习Java的同学看过来了,以下是CSDN作者「ThinkWon」总结的面试题。希望对在准备跳槽或者找工作的同学有点帮助。这一波面试题总体来说基本上能够回答面试官的70%问题。虽然有些小节不够完善的,只能靠你自己多面试多总结了。序号内容链接地址1Java基础知识面试题(2020最新版)https://thinkwon.bl

2020最新Web前端经典面试题及答案

本篇收录了一些大厂面试中经常会遇到的经典面试题,并且我做好了整理分类。虽然今年的金九银十已经过去了,但是可以为明年的金三银四做装备啊,相信每一个跳槽季都有很多的前端开发者蠢蠢欲动,通过对本篇知识的整理以及经验的总结,希望能帮到更多的前端面试者。好了,那我接下来就开始正文咯。PS:内容超长,请注意!HTML篇1.你是怎么理解HTML