Java常量池详解之抓狂的面试题

标签: java 常量 面试 | 发表时间:2014-02-04 21:50 | 作者:sichunli_030
出处:http://www.iteye.com

今天My partner问我一个让他头疼的Java question,求输出结果

 

public class Resule {

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

	public static void main(String[] args) {
		objPoolTest();
	}
}

 

输出结果:

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发现:

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

从这个静态块可以看出,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)),所以他们不是同一个引用。

 

http://developer.51cto.com/art/201111/302748.htm



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 常量 面试] 推荐:

Java常量池详解之抓狂的面试题

- - 编程语言 - ITeye博客
今天My partner问我一个让他头疼的Java question,求输出结果. 看起来比较Easy的问题,但是Console输出的Result和我们所想的确恰恰相反,我们就疑惑了,这是为什么咧. 最后通过网上搜索得知Java为了提高性能提供了和String类一样的对象池机制,当然Java的八种基本类型的包装类(Packaging Type)也有对象池机制.

java面试题

- - Java - 编程语言 - ITeye博客
 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面. 抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节. 抽象包括两个方面,一是过程抽象,二是数据抽象.  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法. 对象的一个新类可以从现有的类中派生,这个过程称为类继承.

JAVA面试精选【Java基础】

- - CSDN博客编程语言推荐文章
  这个系列面试题主要目的是帮助你拿轻松到offer,同时还能开个好价钱. 只要能够搞明白这个系列的绝大多数题目,在面试过程中,你就能轻轻松松的把面试官给忽悠了. 对于那些正打算找工作JAVA软件开发工作的童鞋们来说,当你看到这份题目的时候,你应该感动很幸运,因为,只要你把题目中的内容都搞懂了,在笔试的时候就可以游刃有余,通过面试只有半步之遥了,笔试只能反映你的JAVA技能.

Java面试宝典2013版

- - Java - 编程语言 - ITeye博客
Java基础部分......................................................................................................2. 1、一个".java"源文件中是否可以包括多个类(不是内部类). 2、Java有没有goto?..........................................................................................2.

Java堆、栈和常量池原理

- - 研发管理 - ITeye博客
一:在JAVA中,有六个不同的地方可以存储数据:  . 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部. 但是寄存器的数量极其有限,所以寄存器由编译器根据需求进行分配. 你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象. ------最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制..

Java常量池理解与总结

- - 移动开发 - ITeye博客
用final修饰的成员变量表示常量,值一旦给定就无法改变. final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池. 在Class文件结构中,最头的4个字节用于存储魔数 Magic Number,用于确定一个文件是否能被JVM接受,再接着4个字节用于存储版本号,前2个字节存储次版本号,后2个存储主版本号,再接着是用于存放常量的常量池,由于常量的数量是不固定的,所以常量池的入口放置一个U2类型的数据(constant_pool_count)存储常量池容量计数值.

Java堆栈常量池深入

- - Java - 编程语言 - ITeye博客
转自: http://uule.iteye.com/blog/1417299. 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中.

UC优视广州Java面试题

- - 企业架构 - ITeye博客
学习笔记,转自: http://www.iteye.com/topic/1033375. 学习笔记,转自: http://download.csdn.net/detail/ht99582/5892979. 一是CPU操作的快慢,二是IO操作的快慢. 赋值和计算,如:m = i*j;. 流程控制,如:while(true) { i ++;}.

一次印象深刻的java面试

- - 编程语言 - ITeye博客
1.String、StringBuffer、StringBuilder的区别. 2.冒泡算法的时间复杂度. 3.部门表 dept  包含deptno编号,deptname 名称  ,adress地址. 员工表emp  包含empno编号,empname名称,sal工资,deptno部门编号. (1).一条sql语句查询出所有高于部门平均公司的员工信息(包含部门名称).

知名公司的Java面试题

- - ImportNew
查看不同公司新鲜真实的Java面试题,摘自Glassdoor.com. 假设有一个 getNextparson() 方法返回 Person 对象,Person 类实现了 comparable 接口,现在从文件中读取记录并排序,然后给出前 1000 条记录,纸上作答. 写一个函数,传入 2 个有序的整数数组,返回一个有序的整数数组.