谈谈Integer中的静态类IntegerCache
学习的本质就是一个赋值的过程,用新知识来覆盖你的旧知识或者无知(null)。掌握知识是自己的, 分享知识,才能帮助更多的人,创造更大的价值。学贵以恒,以此自勉,与君共享。----曦阳X
上次在博客园看到有关IntegerCache的文章,回想起之前一次面试的时候也遇到过这种题,当时知道有IntegerCache这个东西会缓存-128到127之间的数据,但并没有深入研究下,因此今天再深入分析下这个类,先看看下面一段代码:
Integer int1 = 20;
Integer int2 = 20;
Integer int3 = 128;
Integer int4 = 128;
Integer int5 = new Integer(20);
System.out.println(int1 == int2);
System.out.println(int3 == int4);
System.out.println(int1 == int5);
如果不了解Integer内部的缓存机制,可能会对此一脸懵逼:这还有啥好比较的,20和128都是常量,前2个肯定都是true,Integer是对象类,每次new出来的对象都应该在不同的内存中,== 比较连地址都不等,肯定都是false。事实上,如果你真这么想就错了。
其实按照上学时的经验我们也会怀疑:这么简单肯定有问题,出题人这么傻会出个这种题?没错,越是简单的地方往往越容易采坑,今天就来谈谈Integer中的静态类IntegerCache问题。
先说下上面的答案:true,false,false;后面再分析原因。
下面是Integer中的静态类IntegerCache的源码,我们来一点点分析:
IntegerCache的源码其实很简单,就是定义了一个high和一个low上下限,这2个值就是用于存储Integer的缓存对象,目的也很明确:提高内存理由率和效率,类似的缓存机制还有8种基本数据类型中除了Double和Float外的6种,比如ShortCache,ByteCache等,而之所以Double和Float没有缓存机制,是因为double、float是浮点型的,没有经常使用到的数据,缓存效果没有其它几种类型使用效率高。除了IntegerCache稍复杂,其他都很简单。不得不说,JDK的作者个个都是天才,代码写得由简洁又巧妙,当然好多代码功力不够也不太好看懂。
还有就是定义了一个Integer类型的Cache数组,目的就是存放缓存的Integer对象。下面看下static静态代码块。
static {
// high value may be configured by property
int h = 127;
//意味着可以通过JVM参数java.lang.Integer.IntegerCache.high来设置缓存的最大值
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
//如果设置了Cache的最大值,就将该最大值与127比较,取其中较大的一个作为缓存的最大值。意味着假如设置的最大值为100,那其实是不会生效的,这么做估计是为了尽可能利用缓存,达到整体性能较好,当然最大值也不能超过Integer.MAX_VALUE
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
//这里得到的h是新建Integer数组的Size,因为low是-128,所以low前面要带个-号,其实就是相加,-1是把0也算上
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;
//初始化IntegerCache
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() {}
}
通过上面分析,我们知道IntegerCache存的其实默认就是-128到127之间的256个Integer对象,这些对象是存在java常量区的。当执行Integer int1 = 20的时候,编译器会自动进行装箱操作,实际执行了Integer.valueOf(int i)方法,同样的,如果是拆箱操作,执行的就是Integer.intValue()方法,下面来看看valueOf(int i)方法的源码:
这么看就很清晰了,当进行自动装箱的时候,会先判断这个值是否在IntegerCache的low和high之间,如果在,就返回IntegerCache中缓存的Integer对象,再来看看开始的题目:
20是在-128到127之间,因此不会新建对象,都是IntegerCache中的对象,因此int1和int2相等
同理:128超过了IntegerCache.high,因此新建了2个不同的对象(存在堆区,在JVM内存中地址不等),所以int3 == int4 为false
至于int1 和int5,由于int1是存在java常量区,int5是存在java的堆区,因此2者也不相等,故也是false。
结尾:看到这个静态内部类,又想发散下静态内部类的加载时间和机制,以及java中静态导入的问题,下次再来讲讲这2个问题
谈谈Integer中的静态类IntegerCache的更多相关文章
- Integer 中的缓存类IntegerCache
2014年去某公司笔试的时候遇到这么一道题: public class Test { public static void main(String[] args) { Integer int1 = I ...
- 对Integer类中的私有IntegerCache缓存类的一点记录
对Integer类中的私有IntegerCache缓存类的一点记录 // Integer类有内部缓存,存贮着-128 到 127. // 所以,每个使用这些数字的变量都指向同一个缓存数据 // 因此可 ...
- Integer 中的缓存类 IntegerCache
我们先看一段代码: public class TestAutoBoxing { public static void main(String[] args) { //-128到127之间 Intege ...
- java的Integer中也会有缓存
在上篇<java的自动拆箱会发生NPE>博客中接收了java中的Integer中的自动拆箱产生的NPE,其实对于所有的包装类来说都是一样的,都会产生这样的问题,大家需要举一反三,做学问学知 ...
- 谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持
谈谈WCF中的Data Contract(3):WCF Data Contract对Collection & Dictionary的支持 在本篇文章上一部分Order Processing的例 ...
- JAVA中MESSAGEBOX,静态类直接引用
原文:JAVA中MESSAGEBOX,静态类直接引用 package cisdi.mes.wrm.mcode.serviceImpl; import javax.persistence.Entity; ...
- 谈谈JAVA中的安全发布
谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...
- 谈谈CSS中一些比较"偏门"的小知识
前面我写了:谈谈html中一些比较"偏门"的知识,现在这篇(主要)想谈谈个人所见的CSS一些小知识点,加深印象:同时也希望有需要的人能有收获! 1.常见的浏览器内核: 以IE为代表 ...
- 谈谈WPF中的CollectionView与CollectionViewSource (1)
原文:谈谈WPF中的CollectionView与CollectionViewSource (1) 谈谈WPF中的CollectionView与CollectionViewSource (1) ...
随机推荐
- Linux之dstat命令
dstat命令是一个用来替换vmstat.iostat.netstat.nfsstat和ifstat这些命令的工具,是一个全能系统信息统计工具.与sysstat相比,dstat拥有一个彩色的界面,在手 ...
- rest get post 请求工具_restclient.jar
下载 :restclient.jar 启动命令 : java -jar restclient.jar 界面如图所示:
- Dede友情链接和分页列表和内容分页去掉小圆点LI标签
我用了一个比较老式的模板,友情链接和列表页底下的一段分页导航会自动获取LI标签,导致错位.每段文字前还多出一个可恶的黑色实心小圆点,心想肯定是LI标签在搞怪,于是把模板文件和样式文件都翻看了一个底朝天 ...
- Dedecms标签arclistsg调用单表模型出错的解决方法
使用arclistsg标签调用分类信息等单表模型出错提示Column 'id' in where clause is ambiguous, 修改文件:include\taglib\arclistsg ...
- UIView剖析之Draw、Size、Layout方法
一.基于UIView的Layer的方法 关于UIView的Layer,IOS提供了三个方法: 1.layoutSubviews 在iOS5.1和之前的版本,此方法的缺省实现不会做任何事情(实现为空), ...
- jsp连接sqlite、Sqlite相对路径绝对路径问题(转)
转自 http://blog.csdn.net/sxy12138/article/details/52304884 假如在java中, # 数据库连接jdbc.jdbc-url=jdbc:sqlit ...
- jQuery开发插件的两个方法 js 深浅拷贝
1.jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法.由全局函数来调用, 主要是用来拓展个全局函数 2.jQuery.fn.extend(object);为jQu ...
- javascript实现多线程提升项目加载速度
以前大家都认为js是单线程执行的,假如我们要执行一些耗时的操作,比如加载一张很大的图片,我们可能需要一个进度条来让用户进行等待,在等待的过程中,整个js线程会被阻塞,后面的代码不能正常运行,这可能大大 ...
- css清除浮动好方法
1.clear:both ==>IE6,7会有高度,所以去高度需要.clear{ clear:both; height:0px; margin:0; padding:0; width:0; bo ...
- Error: unknown argument: '-websockets'
参考原文:http://www.cocoachina.com/bbs/read.php?tid=194014 解决方法:点击项目右边编辑区域上面有一个building setting找到other l ...