Java的Integer与int互转

摘要:
int转IntegerJava代码inti=0;Integerwrapperi=newInteger;Integer转intJava代码Integerwrapperi=newInteger;inti=wrapperi.intValue();JDK1.5以后的int转IntegerJDK1.5以后,Java为我们提供了更为丰富的转换方法。JDK1.5为Integer增加了一个全新的方法:Java代码publicstaticIntegervalueOf以下代码在JDK1.5的环境下可以编译通过并运行。方法二产生一个新的Integer对象。Java代码/**返回一个表示指定的int值的Integer实例。这是相当不划算的,IntegerCache.cache很好的起到了缓存的作用。Java代码Integerwrapperi=newInteger;inti=wrapperi;附:AutoBoxing与UnBoxing带来的转变在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀。之后再次转换为Integer。此特性同样适用于MapJava代码Mapmap=newHashMap();intx=1;Integery=newInteger;intz=3;map.put;//x自动转换成Integer。
int转Integer
Java代码收藏代码
  1. inti=0;
  2. Integerwrapperi=newInteger(i);


Integer转int
Java代码收藏代码
  1. Integerwrapperi=newInteger(0);
  2. inti=wrapperi.intValue();




JDK1.5以后的int转Integer
JDK1.5以后,Java为我们提供了更为丰富的转换方法。

其中最值得一提的就是自动装包/自动拆包(AutoBoxing/UnBoxing)。
此功能大大丰富了基本类型(primitive type)数据与它们的包装类(Wrapper Class)
的使用。

由于AutoBoxing的存在,以下代码在JDK1.5的环境下可以编译通过并运行。
Java代码收藏代码
  1. inti=0;
  2. Integerwrapperi=i;


还有其他方法?
JDK1.5为Integer增加了一个全新的方法:
Java代码收藏代码
  1. publicstaticIntegervalueOf(inti)

以下代码在JDK1.5的环境下可以编译通过并运行。
Java代码收藏代码
  1. inti=0;
  2. Integerwrapperi=Integer.valueOf(i);


此方法与new Integer(i)的不同处在于:
方法一调用类方法返回一个表示指定的 int 值的 Integer 实例。
方法二产生一个新的Integer对象。

JDK API文档中对这个新的valueOf方法有明确的解释:
如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能。

但这个解释有点晦涩难懂。为什么该方法有可能通过缓存经常请求的值而显著提高性能?

通过反编译工具查看valueOf方法。
Java代码收藏代码
  1. /*
  2. *返回一个表示指定的int值的Integer实例。如果不需要新的Integer实例,则
  3. *通常应优先使用该方法,而不是构造方法Integer(int),因为该方法有可能通过
  4. *缓存经常请求的值而显著提高空间和时间性能。
  5. *@paramian<code>int</code>value.
  6. *@returna<tt>Integer</tt>instancerepresenting<tt>i</tt>.
  7. *@since1.5
  8. */
  9. publicstaticIntegervalueOf(inti){
  10. finalintoffset=128;
  11. if(i>=-128&&i<=127){//mustcache
  12. returnIntegerCache.cache[i+offset];
  13. }
  14. returnnewInteger(i);
  15. }


可以看到对于范围在-128到127的整数,valueOf方法做了特殊处理。
采用IntegerCache.cache[i + offset]这个方法。
从名字,我们可以猜出这是某种缓存机制。

进一步跟踪IntegerCache这个类,此类代码如下
Java代码收藏代码
  1. /*
  2. *IntegerCache内部类
  3. *其中cache[]数组用于存放从-128到127一共256个整数
  4. */
  5. privatestaticclassIntegerCache{
  6. privateIntegerCache(){}
  7. staticfinalIntegercache[]=newInteger[-(-128)+127+1];
  8. static{
  9. for(inti=0;i<cache.length;i++)
  10. cache[i]=newInteger(i-128);
  11. }
  12. }


这就是valueOf方法真正的优化方法,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当 i>127 或 i<-128 时,返回的是Integer类对象。

再举一个经常被提到的例子
Java代码收藏代码
  1. Integeri=100;
  2. Integerj=100;
  3. //printtrue
  4. System.out.println(i==j);

此时的 i=IntegerCache.cache[i + 128] = IntegerCache.cache[228],
同样j = IntegerCache.cache[j + 128] = IntgerCache.cache[228]
因此 Integer引用i中存储的是cache数组第228号元素的地址。同理j也是同一个cache数组的第228号元素的地址(因为cache是Integer的static数组,只有一个)。
i==j比较的是引用地址,因此返回true。

Java代码收藏代码
  1. Integeri=200;
  2. Integerj=200;
  3. //printfalse
  4. System.out.println(i==j);

此时的 i=new Integer(200); 同样j=new Integer(200) 。
两次都在堆中开辟了Integer的对象。
i 和 j 中存储的堆的对象地址是完全不同的。i==j 自然返回false。


引入缓存机制的作用何在?

接着上面的例子,假如我们在编程时大量需要值为100(100的范围在-128到127之间)的Integer对象。如果只能通过new来创建,需要在堆中开辟大量值一样的Integer对象。
这是相当不划算的,IntegerCache.cache很好的起到了缓存的作用。
当我们需要Integer i = 100的时候,直接从cache中取出第[100+128]号元素的地址赋值给引用i,再次需要Integer j = 100时,还是直接去这个地址赋值给j。是不是省去了在堆中不停的创建对象的代价了(空间,时间上的消耗都很大)。 这就是valueOf方法真正的提高性能之处。
正如JDK API文档对valueOf(int i)方法的描述,该方法有可能通过缓存经常请求的值而显著提高空间和时间性能。

结论

valueOf(int i)的优化只针对于范围在-128到127的整数。




JDK1.5以后的Integer转int
由于UnBoxing的存在,以下代码在JDK1.5的环境下可以编译通过并运行。
Java代码收藏代码
  1. Integerwrapperi=newInteger(0);
  2. inti=wrapperi;








附:AutoBoxing与UnBoxing带来的转变
在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀。

以下代码在JDK1.5中成为了可能,试想下在JDK1.5之前该如何实现这段代码?
Java代码收藏代码
  1. intx=1;
  2. Collectioncollection=newArrayList();
  3. collection.add(x);//AutoBoxing,自动转换成Integer.
  4. Integery=newInteger(2);
  5. collection.add(y+2);//y+2为UnBoxing,自动转换成int。之后再次转换为Integer。


此特性同样适用于Map
Java代码收藏代码
  1. Mapmap=newHashMap();
  2. intx=1;
  3. Integery=newInteger(2);
  4. intz=3;
  5. map.put(x,y+z);//x自动转换成Integer。y+z自动转换成int。之后再次转换为Integer。

免责声明:文章转载自《Java的Integer与int互转》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇awk 调用 shell 命令,并传递参数navicat查看MySQL数据库、表容量大小下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

ESXi挂载NFS共享存储

使用万兆交换机,ESXi使用NFS协议连接存储。本文介绍的是通过NFS协议挂载共享存储上的VS01卷,共享存储上已经赋予ESXi主机访问该卷的权限。...

Vue跨层级传递slot的方法

但是我需要通过插槽在父组件中指定一个模板,而B组件引用C组件。组件C的部分模板需要在组件A中配置。模板引用A组件:{{node.text}}&lt;模板引用B组件:spanslot=“nodeMenu”slot scope=“{node}”&gt;node=“node”&gt;/span&gt;/div&gt;2.2如...

流控制、FlowControl

作用就是防止网络拥堵时导致的“丢包”问题,大致的工作原理就是当链路两端的设备有一端忙不过来了,他会给另外一端的设备发一个暂停发包的命令,通过这种方式来缓解压力,解决丢包问题。看上去流控制应该是个非常好的防止丢包的方法,但是为什么我们还要在无盘上关闭他呢?...

fiddler抓包+雷电模拟器 完成手机app抓包的配置

找到系统应用,点击设置,点击无线网络WLAN—˃左键常按点击已连接网络—˃修改网络鼠标左键长按在桌面找到下面这个文件之后双击打开上面证书弄完之后。可以说本机已经安装过证书了,如果你能在模拟器上找到这个证书就不用将这个证书再拉入模拟器了在模拟器中打开系统应用—˃设置—˃安全—˃从SD卡安装。找到FiddlerRoot.cer文件,按提示导入即可,注意在此过程需...

C# Task详解

1.任务线程池的优点与线程相比有很多优点,但线程池不方便使用。例如:◆ ThreadPool不支持线程取消、完成和失败通知等交互操作;◆ ThreadPool不支持线程执行顺序;在过去,如果开发人员想要实现上述功能,他们需要完成大量额外的工作。现在,FCL提供了一个更强大的概念:任务。任务基于线程池执行...

GitLab 数据库

要访问GitLab数据库步骤中使用的DockerGitlab,首先输入容器dockerexec-itgitlab/bin/bash ``查找数据库配置文件``bash/var/opt/GitLab/gitlabrails/etc/database yml内容如下,记录数据库配置信息production:adapter:postgresqlencoding:u...