常量缓存与integer比较_Java常量池详解之Integer缓存

一个Java question,求输出结果

public class IntegerTest {

public static void main(String[] args) {

objPoolTest();

}

public static void objPoolTest() {

Integer i1 = 40;

Integer i2 = 40;

Integer i3 = 0;

Integer i4 = new Integer(40);

Integer i5 = new Integer(40);

Integer i6 = new Integer(0);

System.out.println("i1=i2 \t" + (i1 == i2));

System.out.println("i1=i2+i3 \t" + (i1 == i2 + i3));

System.out.println("i4=i5 \t" + (i4 == i5));

System.out.println("i4=i5+i6 \t" + (i4 == i5 + i6));

System.out.println();

}

}

输出结果是

i1=i2 true

i1=i2+i3 true

i4=i5 false

i4=i5+i6 true

看起来比较Easy的问题,但是Console输出的Result和我们所想的确恰恰相反,我们就疑惑了,这是为什么咧?

最后通过网上搜索得知Java为了提高性能提供了和String类一样的对象池机制,当然Java的八种基本类型的包装类(Packaging Type)也有对象池机制。

Integer i1=40;Java在编译的时候会执行将代码封装成Integer i1=Integer.valueOf(40);通过查看Source Code发现

/**

* Returns a Integer instance representing the specified

* int value.

* If a new Integer instance is not required, this method

* should generally be used in preference to the constructor

* {@link #Integer(int)}, as this method is likely to yield

* significantly better space and time performance by caching

* frequently requested values.

*

* @param i an int value.

* @return a Integer instance representing i.

* @since 1.5

*/

public static Integer valueOf(int i) {

final int offset = 128;

if (i >= -128 && i <= 127) { // must cache

return IntegerCache.cache[i + offset];

}

return new Integer(i);

}

Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256;Integer类中还有一个Static Block(静态块)

static {

for(int i = 0; i < cache.length; i++)

cache[i] = new Integer(i - 128);

}

从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer i1=40时,JVM会直接在该在对象池找到该值的引用。   也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为40的对象,如果有直接返回该对象的引用;如果没有,则使用New keyword创建一个对象,并返回该对象的引用地址。因为Java中【==】比较的是两个对象是否是同一个引用(即比较内存地址),i2和i2都是引用的同一个对象,So i1==i2结果为”true“;而使用new方式创建的i4=new Integer(40)、i5=new Integer(40),虽然他们的值相等,但是每次都会重新Create新的Integer对象,不会被放入到对象池中,所以他们不是同一个引用,输出false。

对于i1==i2+i3、i4==i5+i6结果为True,是因为,Java的数学计算是在内存栈里操作的,Java会对i5、i6进行拆箱操作,其实比较的是基本类型(40=40+0),他们的值相同,因此结果为True。

好了,我想说道这里大家应该都会对Integer对象池有了更进一步的了解了吧,我在诺诺的问一句如果把40改为400猜猜会输出什么?

i1=i2 false

i1=i2+i3 true

i4=i5 false

i4=i5+i6 true

这是因为Integer i1=400,Integer i2=400他们的值已经超出了常量池的范围,JVM会对i1和i2各自创建新的对象(即Integer i1=new Integer(400)),所以他们不是同一个引用。

【转】Java常量池详解

今天My partner问我一个让他头疼的Java question,求输出结果: /** * * @author DreamSea 2011-11-19 */ public class Intege ...

Java常量池详解

转自:http://www.cnblogs.com/iyangyuan/p/4631696.html jvm虚拟内存分布图: 程序计数器:JVM执行程序的流水线. 本地方法栈:JVM调用操作系统方法所 ...

java中的String类常量池详解

test1: package StringTest; public class test1 { /** * @param args */ public static void main(String[ ...

《Java虚拟机原理图解》 1&period;2&period;3、Class文件中的常量池详解(下)

CONSTANT_Fieldref_info, CONSTANT_Name_Type_info) 一般而言,我们在定义类的过程中会定义一些 field 字段,然后会在这个类的其他地方(如方法中)使用到 ...

Java线程池详解(二)

一.前言 在总结了线程池的一些原理及实现细节之后,产出了一篇文章:Java线程池详解(一),后面的(一)是在本文出现之后加上的,而本文就成了(二).因为在写完第一篇关于java线程池的文章之后,越发觉 ...

19、java内存分配 常量池详解

在class文件中,“常量池”是最复杂也最值得关注的内容. Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int.long等等)和对象型(如Stri ...

java常量池詳解

一.相关概念 什么是常量用final修饰的成员变量表示常量,值一旦给定就无法改变!final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池在Clas ...

《Java虚拟机原理图解》 1&period;2&period;2、Class文件中的常量池详解(上)

我的上一篇文章 1.class文件基本组织结构中已经提到了class的文件结构,在class文件中的魔数.副版本号.主版本之后,紧接着就是常量池的数据区域了,如下 ...

Java虚拟机原理图解-- 1&period;2&period;2、Class文件中的常量池详解(上)&lbrack;转&rsqb;

NO1.常量池在class文件的什么位置? 我的上一篇文章 1.class文件基本组织结构中已经提到了class的文件结构,在class文件中的魔数.副版本号.主 ...

随机推荐

C&num; 写的一个生成随机汉语名字的小程序

最近因为要做数据库相关的测试,频繁使用到测试数据,手动添加太过于麻烦,而且复用性太差,因此干脆花了点时间写了一个生成随机姓名和相关数据的类,贴在这里,有需用的同志们可以参考一下.代码本身质量不好,也不 ...

JSP隐含变量和Spring中Model在EL表达式中的读取顺序

偶然中存在着必然,必然中存在着偶然 偶然出现的bug,必然存是由代码的不合理甚至错误的 代码逻辑越长,越复杂,就越容易出现bug 之前项目里几次偶然出现了一个bug,简单的描述就是第一次新增了之后进行 ...

&lbrack;技术学习&rsqb;js正则表达式汇总

一.常用正则表达式关键字 ".":任意字符 "*":任意个数 "+":任意个数,至少一个 "?":0-1个 " ...

php中GD库的简单使用

在php中需要图像处理的地方GD库会发挥重要的作用,php可以创建并处理包括GIF,PNG,JPEG,WBMP以及XPM在内的多种图像格式,简单的举几个例子: 1.用GD库会创建一块空白图片,然后绘制 ...

filebeat-kafka日志收集

filebeat-kafka日志收集 由于线上的logstash吃掉大量的CPU,占用较多的系统资源,就想找其它的组件替代.我们的日志需要收集并发送到kafka,生成的日志已经是需要的数据,不用过滤. ...

我的es6笔记

变量 1. let 和 const 声明的变量不在window上了 2. es6中对于块级作用域里的函数声明实现不统一,要避免在大括号里声明函数,尽量用函数表达式来替代. 3. let和const声明 ...

eclipse中的项目无法添加到server下?

servers视图中不能将工作空间中的项目通过add and remove添加到新建的server下.解决方法如下: 1.右键点击项目,选择properties 2.点击Project facets( ...

C&num;SpinWait和volatile一点温习

今天看ConcurrentQueue 源码发现里面居然没有用到lock,我记得ConcurrentDictionary里面是有lock的,lock的是字典里面每一个key,但是Con ...

LeetCode Python 位操作 1

Python 位操作: 按位与 &, 按位或 | 体会不到 按位异或 ^ num ^ num = 0 左移 << num << 1 == num * 2**1 右移 & ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值