Integer. valueOf()可以将基本类型int转换为包装类型Integer,或者将String转换成Integer,String如果为Null或“”都会报错。

Integer. valueOf()是高效的

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = 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;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() {}}

从他的实现方法可以看出他int在[-128,127]之间的时候他会直接拿缓存,而不会new Integer(),Integer.valueOf()方法基于减少对象创建次数和节省内存的考虑,缓存了[-128,127]之间的数字。此数字范围内传参则直接返回缓存中的对象。在此之外,直接new出来。

下面我们来看一道选择题,就是关于Integer.valueOf()的知识,题目如下:

A.System.out.println(i01== i02); 
B.System.out.println(i01== i03); 
C.System.out.println(i03== i04); 
D.System.out.println(i02== i04);

答案呢,我也做对了,但是也是靠排除法做对的,至于这道题考察的具体细节问题,我当时没考虑,不过等我查看了Integer的相关源码时,茅舍顿开。答案这里我这里先不公布,我们慢慢开始分析。

分析

选项A

  选项A中比较的是i01和i02,Integer i01=59这里涉及到自动装箱过程,59是整型常量,经包装使其产生一个引用并存在栈中指向这个整型常量所占的内存,这时i01就是Integer 的引用。 
  而int i02=59由于int是基本类型,所以不存在引用问题,直接由编译器将其存放在栈中,换一句话说,i02本身就是59。那么System.out.println(i01== i02)结果任何呢?这里涉及到了拆箱的过程,因为等号一边存在基本类型所以编译器后会把另一边的Integer对象拆箱成int型,这时等号两边比较的就是数值大小,所以是true。

好了,到了这里,你有没有想到这样一个问题:如果是Integer i01=59;Integer i02=59;然后System.out.println(i01== i02)的结果是?可能你会说比较数值大小所以相等啊,也有可能说等号两边对象引用,所以比较的是引用,又因为开辟了不同的内存空间,所以引用不同所以返回false。可是正确答案是:true. 
再来看这个问题::如果是Integer i01=300;Integer i02=300;然后System.out.println(i01== i02)的结果是? 你可能说上面你不是说了true嘛,怎么还问这样的问题,可是这次的答案是false。你是否会吃惊?大牛除外,我是小白,求不打脸!
  

解析:当靠想象无法解决问题的时候,这是就要看源代码了!!很重要!我们可以在Integer类中找到这样的嵌套内部类IntegerCache,这个类就是在Integer类装入内存中时,会执行其内部类中静态代码块进行其初始化工作,做的主要工作就是把一字节的整型数据(-128-127)装包成Integer类并把其对应的引用存入到cache数组中,这样在方法区中开辟空间存放这些静态Integer变量,同时静态cache数组也存放在这里,供线程享用,这也称静态缓存。 
  所以当用Integer 声明初始化变量时,会先判断所赋值的大小是否在-128到127之间,若在,则利用静态缓存中的空间并且返回对应cache数组中对应引用,存放到运行栈中,而不再重新开辟内存。 
  所以对于Integer i01=59;Integer i02=59;**i01 和 i02是引用并且相等都指向缓存中的数据,所以返回true。而对于**Integer i01=300;Integer i02=300;因为其数据大于127,所以虚拟机会在堆中重新new (开辟新空间)一个 Integer 对象存放300,创建2个对象就会产生2个这样的空间,空间的地址肯定不同导致返回到栈中的引用的只不同。所以System.out.println打印出false。

补充:为什么1个字节的数据范围是-128到127呢,因为Java中数据的表示都是带符号数,所以最高位是用来表示数据的正负,0表示正数,1表示负数,所以正数最大的情况对应的二进制数为:01111111,负数最小对应的二进制数为:10000000.

B选项

  从上面的分析,我们已经知道Integer i01=59返回的是指向缓存数据的引用。那么Integer.valueOf(59)返回的是什么或者操作是什么呢? 
  这个函数的功能就是把int 型转换成Integer,简单说就是装包,那他是新创建一个对象吗?还是像之前利用缓存的呢?有了之前的经验,肯定想到的是利用缓存,这样做既提高程序速度,又节约内存,何乐而不为? 
来看一下源代码:

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

很明显跟之前的思想一致,若在-128到127范围,直接返回该对象的引用,否则在堆中重新new 一个。 
到这,System.out.println(i01== i03)的结果毋庸置疑就是true.

选项C

  Integer.valueOf(59)返回的是已缓存的对象的引用,而Integer i04 = new Integer(59)是在堆中新开辟的空间,所以二者的引用的值必然不同,返回false,这道题呢就选C

选项D

  System.out.println(i02== i04) i02是整型变量,i04是引用,这里又用到了解包,虚拟机会把i04指向的数据拆箱为整型变量再与之比较,所以比较的是数值,59==59,返回true.


出一道题:

System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));
System.out.println(Integer.parseInt("128")==Integer.valueOf("128"));

输出是:

true

false

true

回答#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之间的一个值。

有了这个概念,就可以知道上面三行代码之间的区别。

new Integer(123);

显示创建了一个新的Integer对象。

Integer.parseInt("123");

解析完字符串后返回一个int值。

Integer.valueOf("123");

这种情况比其他的要更复杂一些。首先进行了字符串解析,然后如果解析的值位于-128和127之间,就会从静态缓存中返回对象。如果超出了这个范围,就会调用Integer()方法并将解析的值作为参数传入,得到一个新的对象。

现在,让我们看一下问题中的3个表达式。

Integer.valueOf("127")==Integer.valueOf("127");

上面的表达式返回true,因为Integer的值从静态缓存中取了2次,表达式返回了对象与自己比较的结果。因为只有一个Integer对象,所以返回结果为true。

Integer.valueOf("128")==Integer.valueOf("128");

上面的表达式返回false,因为128没有存在静态缓冲区。所以每次在判断相等时等式两边都会创建新的Integer对象。由于两个Integer对象不同,所以==只有等式两边代表同一个对象时才会返回true。因此,上面的等式返回false。

Integer.parseInt("128")==Integer.valueOf("128");

上面的表达式比较的是左边的原始int值128与右边新创建的Integer对象。但是因为int和Integer之间比较是没有意义的,所以Java在进行比较前会将Integer自动拆箱,所以最后进行的是int和int值之间的比较。由于128和自己相等,所以返回true。

注意:此文只适应于jdk7或以上版本,因为jdk6与jdk7的Integer具体实现有差别,详情可查看下源代码.


Integer.parseInt()

Integer.valueof() 和 Integer.parseInt() 的底层都是用的Integer.parseInt(String s ,int radix)这个方法。在这里给这个方法做一下解释。

  Integer.parseInt(String s ,int radix),radix用来表示传进来的值是什么进制的,并返回10进制的 int 类型的结果

  比如Integer.parseInt(“A”,16),则输出结果为10进制的10,其中16表示"A"是一个16进制的值。

  根据:Character.MIN_RADIX=2和Character.MAX_RADIX=36 则,parseInt(String s, int radix)参数中radix的范围是在2~36之间,超出范围会抛异常。其中s的长度也不能超出7,否则也会抛异常。其中限制在36位之内是因为数字加字母刚好可以表示到36位,比如Integer.parseInt(“Z”,36),输出结果为35。

  以下为parseInt(String s ,Int radix)的源代码实现。

/*** 字符串转换成整数* @param s 待转换字符串* @param radix   进制* @return*/
public static int parseInt(String s,int radix){//边界值处理if(s==null)throw new NumberFormatException("null");if(radix<Character.MIN_RADIX){throw new NumberFormatException("radix "+radix+" less than Character.MIN_RADIX");}if(radix>Character.MAX_RADIX){throw new NumberFormatException("radix "+radix+" greater than Character.MAX_RADIX");}//最终返回的结果的负数形式int result=0;//判断是否为负数boolean negative=false;//字符串偏移指针int i=0;int digit;int max=s.length();//最大边界值int limit;//最大边界值右移一位int multmin;if(max>0){//处理符号if(s.charAt(0)=='-'){negative=true;//边界值为0x80000000limit=Integer.MIN_VALUE;i++;}else{//边界值为-0x7ffffffflimit=-Integer.MAX_VALUE;}//计算multmin 值 ,multmin = -214748364 负数跟整数的limit是不同的multmin=limit/radix;if(i<max){digit=Character.digit(s.charAt(i++), radix);if(digit<0){throw NumberFormatException.forInputString(s);}else{result=-digit;}}//开始循环追加数字,比如输入“123” 10进制数while(i<max){//获取字符转换成对应进制的整数,如上,这里第一次循环获取1//第二次循环获取2//第三次循环获取3digit=Character.digit(s.charAt(i++), radix);if(digit < 0){throw NumberFormatException.forInputString(s);}//判断,在追加后一个数字前,判断其是否能能够在继续追加数字,比如multmin = 123//那么再继续追加就会变为123*10+下一个数字,就会溢出if(result < multmin){throw NumberFormatException.forInputString(s);}//第一次循环   result = 0;//第二次循环   result = -10;//第三次循环   result = -120;result*=radix;if(result<limit+digit){//第一次循环  limit + digit = -2147483647+1;//第二次循环   limit + digit = -2147483647+2;//第三次循环   limit + digit = -2147483647+3;throw NumberFormatException.forInputString(s);}result-=digit;//第一次循环 result = -1;//第二次循环 result = -12;//第三次循环 result = -123;}}else{throw NumberFormatException.forInputString(s);}if(negative){if(i>1){return result;}else{throw NumberFormatException.forInputString(s);}}else{//negative 值为false,所以 -result = -(-123) = 123  返回结果return -result;}
}

关键点:

  1. 正数的边界值为1至0x7fffffff;负数的边界值为-1至0x80000000;
  2. 代码中将所有数据当做负数(正数)来处理,最后处理符号问题;
  3. 方法中multmin这个变量是为了在循环中result*=radix不会发生越界;

Integer.parseInt("")、 Integer.valueOf("")new Integer("")它们之间有什么区别呢?我们可以分别看一下它们的源码

//Integer.parseInt("")
public static int parseInt(String s) throws NumberFormatException {return parseInt(s,10);
}
//Integer.valueOf("")
public static Integer valueOf(String s) throws NumberFormatException {return Integer.valueOf(parseInt(s, 10));
}
//new Integer("")
public Integer(String s) throws NumberFormatException {this.value = parseInt(s, 10);
}

从源码中可以看出,Integer.valueOf("")Integer.parseInt("")内部实现是一样的,它们之间唯一的区别就是Integer.valueOf(“”)返回的是一个Integer对象,而Integer.parseInt(“”)返回的是一个基本类型的int

我们再看Integer.valueOf("")new Integer(""),它们同样返回的是一个Integer对象,但它们又有什么区别呢?我们再进入Integer.valueOf(parseInt(s, 10) )方法内部:

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}

我们可以看到,Integer.valueOf("")会用到IntegerCache对象,当IntegerCache中存在时就从cache中取,不存在时才会调用new Integer(i)构造函数返回一个Integer对象。所以Integer.valueOf("")会用到cache,其效率可能会比用构造函数new Integer(i)

关于IntegerCache,在-127~128之间的值都会被cache,所以当我们要的值位于这个区间时返回的都是同一个实例,例如:

System.out.println(Integer.valueOf(5) == Integer.valueOf(5)); System.out.println(Integer.valueOf(500) == Integer.valueOf(500));

输出结果:

true //会用到缓存false //不会用到缓存

Integer.valueof()和Integer.parseInt()的区别相关推荐

  1. integer比较_Java整数缓存Integer.valueOf(127)==Integer.valueOf(127)为True

    在一次采访中,我的一个朋友被问到,如果我们有两个整数对象,Integer a = 127; Integer b = 127;为什么要a == b的值为true ?在本文中,我将尝试回答这个问题,并解释 ...

  2. Integer.valueof()与Integer.parseInt()与intValue()的辨别

    1.valueOf() 方法用于返回给定参数的原生 Number 对象值,参数可以是原生数据类型(即8种基本类型), String等. valueOf()是8中基本数据类型的包装类的静态方法(还有st ...

  3. new Integer()与 Integer.valueOf()区别和联系

    自学练习用,如有错误,还请谅解批评. new Integer 是通过创建Integer对象来实现赋值. valueOf 是使用Integer中的方法来实现的. Integer x = new Inte ...

  4. Integer.valueOf、intValue、Integer.parseInt使用

    我在开发过程中处理人员id筛选,从数据库中查询到人员id转int类型,我用了Integer.valueOf(),筛选过程中使用了如果某一个人员id相等就排除,结果我排除不掉:通过打印日志知道Integ ...

  5. Integer.valueOf(String) 方法之惑

    http://www.importnew.com/9162.html Importnew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的Java开发小组.参与方式请查看小组简介. 有个仁兄在 ...

  6. Java类型转换中valueOf方法和parseInt方法的区别

    在Java的类型转换中,我们经常会使用valueOf或者parseInt(parseFloat/parseDouble等)来转换.这二者有什么区别呢?我们看如下的代码: String inputVal ...

  7. int、Integer、new Integer和Integer.valueOf()的 ==、equals比较

    Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能. Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Cha ...

  8. String.valueOf()和Integer.valueOf()方法的使用

    String.valueOf()的用法 1. 由 基本数据型态转换成 String  String 类别中已经提供了将基本数据型态转换成 String 的 static 方法  也就是 String. ...

  9. new Integer 和 Integer.valueOf 有什么不同

    2019独角兽企业重金招聘Python工程师标准>>> @Testpublic void testHashCode() throws Exception {//[1237514926 ...

最新文章

  1. PythonTip(2)
  2. 如何使用 C# 中的 Action, Func,Predicate
  3. 安全地创建和存储密码
  4. mysql 3种报错_MySQL读取Binlog日志常见的3种错误-阿里云开发者社区
  5. 这样讲原码、反码、补码!学妹连夸我很猛!!
  6. 一个拖拽的效果类和dom-drag.js
  7. 2021新鲜出炉软件测试的真实面试题(一篇足以)
  8. 动态规划之01背包问题(最易理解的讲解)
  9. 用MyEclipse将java文件转换成UML类图
  10. 强行进入远程计算机,远程桌面强制连接命令
  11. 项目组合管理、项目集管理、项目管理和组织级项目管理之间的关系
  12. 计算机中年级排名怎么操作,智学网年级排名查看方法规则介绍
  13. A N S I五个预定义的宏名
  14. ATX电源的基本描述
  15. 2021年南京天印中学高考成绩查询,2021年南京重点高中名单及排名,南京高中高考成绩排名榜...
  16. 阿里云镜像服务 vpc地址 无法 pull
  17. sublimeText3编辑器使用大全
  18. 堆内存和栈内存的区别(通俗版)
  19. 计算机病毒金山毒霸,金山毒霸网络版成为计算机病毒的客星
  20. vasp算表面吸附流程_VASP表面吸附计算实例分析

热门文章

  1. 初学者用js是怎么敲九九乘法表的
  2. _proto_与prototype的关系及区别
  3. html盒子左右边框边距,CSS盒子模型、内外边距、边框、行高、背景
  4. Mock工具库Random学习
  5. 60分钟吃掉三杀模型FiBiNET
  6. 【PTA】炮弹打蚊子
  7. C#实用教程-操作xml文件
  8. Jenkins任务优先级插件
  9. 【同程艺龙面经】一年Java开发经验面经(部门老大面)
  10. 神即道,道法自然,如来--《天道》《遥远的救世主》