今天在ImportNew上看到一篇文章,题目是《Integer.valueOf(String) 方法之惑 》,原文链接:http://www.importnew.com/9162.html
贴上我的测试代码(测试环境JDK_1.6.0_43,原文说JDK6和JDK7对Integer的实现方法不一样,这个我暂时还没有去查源码):
测试代码:
/** * 文件名:IntegerTest.java * * 描述:此处填写文件的描述信息 * * 日期:2014-2-12 * * 本系统是商用软件,未经授权擅自复制或传播本程序的部分或全部将是非法的 * * Copyright(C) ELYT Corporation 2014 * */ package com.jormin.test; import com.jormin.util.LogUtil; /** * <dl> Class Description * <dd> 项目名称:Test * <dd> 类名称:IntegerTest * <dd> 类描述:概述类的作用 * <dd> 创建人:谢乔敏 * <dd> 创建时间:2014-2-12 上午10:34:08 * <dd> 修改人:无 * <dd> 修改时间:无 * <dd> 修改备注:无 * </dl> * @see * @version 1.0 * */ public class IntegerTest { private static final String TAG = LogUtil.DEGUG_MODE ? "IntegerTest" : IntegerTest.class.getSimpleName(); private static final boolean debug = true; public static void main(String[] args) { boolean bl1= Integer.valueOf("127")==Integer.valueOf("127"); boolean bl2= Integer.valueOf("128")==Integer.valueOf("128"); boolean bl3= Integer.parseInt("128")==Integer.valueOf("128"); LogUtil.i(debug,TAG,"【IntegerTest.main()】【bl1="+bl1+",bl2="+bl2+",bl3="+bl3+"】"); } }
测试结果:
【IntegerTest.main()】【bl1=true,bl2=false,bl3=true】
原文分析(摘录):
为什么第一个判断返回了true
而第二个判断返回了false
?127
和128
有什么我不知道的区别吗?(当然除了127
小于128
…)
还有,为什么第三个判断返回了true
?
我看了另一个相关提问的回答,但是我还是不知道它们什么时候返回true还有为什么第二个判断返回false
。
回答#1:
Integer.valueOf(String)
确有一个不同寻常的行为。
valueOf
会返回一个Integer
(整型)对象,当被处理的字符串在-128
和127
(包含边界)之间时,返回的对象是预先缓存的。这就是为什么第一行的调用会返回true
-127
这个整型对象是被缓存的(所以两次valueOf
返回的是同一个对象)——第二行的调用返回false
是因为128
没有被缓存,所以每次调用,都会生成一个新的整型对象,因此两个128
整型对象是不同的对象。
重要的是你要知道在上面的比较中,你实际进行比较的是integer.valueOf
返回的对象引用,所以当你比较缓存外的整型对象时,相等的判断不会返回true
,就算你传个valueOf
的值是相等的也没用。(就像第二行中Integer.valueOf(128)==Integer.valueOf(128))
。想让这个判断返回true
,你需要使用equals()
方法。
parseInt()
返回的不是整型对象,而是一个int
型基础元素。这就是为什么最后一个判断会返回true
,第三行的判断中,在判断相等时,实际比较的是128 == 128
,所以它必然是相等的。
再来说说第三种比较中的一点区别,使得它的结果与第二种比较不一样了:
一个unboxing conversion(一种比较时的转换,把对对象的引用转换为其对应的原子类型)在第三行的比较中发生了。因为比较操作符使用了==
同时等号的两边存在一个int
型和一个Integer
对象的引用。这样的话,等号右边返回的Integer
对象被进一步转换成了int
数值,才与左边进行相等判断。
所以在转换完成后,你实际比较的是两个原子整型数值。这种转换正是你在比较两个原子类型时所期待看到的那样,所以你最终比较了128
等于128
。
回答#2:
Integer
类有一个静态缓存,存储了256个特殊的Integer
对象——每个对象分别对应`-128 和127之间的一个值。
有了这个概念,就可以知道上面三行代码之间的区别。
1 | new Integer(123); |
显示创建了一个新的Integer
对象。
1 | Integer.parseInt( "123" ); |
解析完字符串后返回一个int
值。
1 | Integer.valueOf( "123" ); |
这种情况比其他的要更复杂一些。首先进行了字符串解析,然后如果解析的值位于-128
和127
之间,就会从静态缓存中返回对象。如果超出了这个范围,就会调用Integer()
方法并将解析的值作为参数传入,得到一个新的对象。
现在,让我们看一下问题中的3个表达式。
1 | Integer.valueOf( "127" )==Integer.valueOf( "127" ); |
上面的表达式返回true
,因为Integer
的值从静态缓存中取了2次,表达式返回了对象与自己比较的结果。因为只有一个Integer对象,所以返回结果为true
。
1 | Integer.valueOf( "128" )==Integer.valueOf( "128" ); |
上面的表达式返回false
,因为128
没有存在静态缓冲区。所以每次在判断相等时等式两边都会创建新的Integer
对象。由于两个Integer
对象不同,所以==
只有等式两边代表同一个对象时才会返回true
。因此,上面的等式返回false
。
1 | Integer.parseInt( "128" )==Integer.valueOf( "128" ); |
上面的表达式比较的是左边的原始int
值128
与右边新创建的Integer
对象。但是因为int
和Integer
之间比较是没有意义的,所以Java在进行比较前会将Integer自动拆箱,所以最后进行的是int
和int
值之间的比较。由于128
和自己相等,所以返回true
。
补充说明:
文章没有列出具体的执行环境,jdk版本信息,因此造成不一样的结果,让大家误解了.抱歉.现在说明一下:
此文只适应于jdk7或以上版本,因为jdk6与jdk7的Integer具体实现有差别,详情可查看下源代码.
本文出自 “老谢” 博客,谢绝转载!
原文:http://jormin.blog.51cto.com/6136596/1358292