博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
int与Integer
阅读量:4135 次
发布时间:2019-05-25

本文共 4572 字,大约阅读时间需要 15 分钟。

int转Integer
Java代码
  1. int i = 0;
  2. Integer wrapperi = new Integer(i);
int i = 0;Integer wrapperi = new Integer(i);
Integer转int
Java代码
  1. Integer wrapperi = new Integer(0);
  2. int i = wrapperi.intValue();
Integer wrapperi = new Integer(0);int i = wrapperi.intValue();
JDK1.5以后的int转Integer
JDK1.5以后,Java为我们提供了更为丰富的转换方法。
其中最值得一提的就是自动装包/自动拆包(AutoBoxing/UnBoxing)。
此功能大大丰富了基本类型(primitive type)数据与它们的包装类(Wrapper Class)
的使用。
由于AutoBoxing的存在,以下代码在JDK1.5的环境下可以编译通过并运行。
Java代码
  1. int i = 0;
  2. Integer wrapperi = i;
int i = 0;Integer wrapperi = i;
还有其他方法?
JDK1.5为Integer增加了一个全新的方法:
Java代码
  1. public static Integer valueOf(int i)
public static Integer valueOf(int i)
以下代码在JDK1.5的环境下可以编译通过并运行。
Java代码
  1. int i = 0;
  2. Integer wrapperi = Integer.valueOf(i);
int i = 0;Integer wrapperi = 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. * @param i an <code>int</code> value.
  6. * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
  7. * @since 1.5
  8. */
  9. public static Integer valueOf(int i) {
  10. final int offset = 128;
  11. if (i >= -128 && i <= 127) { // must cache
  12. return IntegerCache.cache[i + offset];
  13. }
  14. return new Integer(i);
  15. }
/*    * 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则    * 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过    * 缓存经常请求的值而显著提高空间和时间性能。     * @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);   }
可以看到对于范围在-128到127的整数,valueOf方法做了特殊处理。
采用IntegerCache.cache[i + offset]这个方法。
从名字,我们可以猜出这是某种缓存机制。
进一步跟踪IntegerCache这个类,此类代码如下
Java代码
  1. /*
  2. * IntegerCache内部类
  3. * 其中cache[]数组用于存放从-128到127一共256个整数
  4. */
  5. private static class IntegerCache {
  6. private IntegerCache(){}
  7. static final Integer cache[] = new Integer[-(-128) + 127 + 1];
  8. static {
  9. for(int i = 0; i < cache.length; i++)
  10. cache[i] = new Integer(i - 128);
  11. }
  12. }
/*    * IntegerCache内部类    * 其中cache[]数组用于存放从-128到127一共256个整数    */  private static class IntegerCache {       private IntegerCache(){}         static final Integer cache[] = new Integer[-(-128) + 127 + 1];         static {           for(int i = 0; i < cache.length; i++)           cache[i] = new Integer(i - 128);       }   }
这就是valueOf方法真正的优化方法,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当 i>127 或 i<-128 时,返回的是Integer类对象。
再举一个经常被提到的例子
Java代码
  1. Integer i=100;
  2. Integer j=100;
  3. //print true
  4. System.out.println(i==j);
Integer i=100;Integer j=100;//print trueSystem.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. Integer i=200;
  2. Integer j=200;
  3. //print false
  4. System.out.println(i==j);
Integer i=200;Integer j=200;//print falseSystem.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. Integer wrapperi = new Integer(0);
  2. int i = wrapperi;
Integer wrapperi = new Integer(0);int i = wrapperi;
附:AutoBoxing与UnBoxing带来的转变
在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀。
以下代码在JDK1.5中成为了可能,试想下在JDK1.5之前该如何实现这段代码?
Java代码
  1. int x = 1;
  2. Collection collection = new ArrayList();
  3. collection.add(x);//AutoBoxing,自动转换成Integer.
  4. Integer y = new Integer(2);
  5. collection.add(y + 2); //y + 2为UnBoxing,自动转换成int。之后再次转换为Integer。
int x = 1; Collection collection = new ArrayList(); collection.add(x);//AutoBoxing,自动转换成Integer. Integer y = new Integer(2); collection.add(y + 2); //y + 2为UnBoxing,自动转换成int。之后再次转换为Integer。
此特性同样适用于Map
Java代码
  1. Map map = new HashMap();
  2. int x = 1;
  3. Integer y = new Integer(2);
  4. int z = 3;
  5. map.put(x,y + z);//x自动转换成Integer。y+z自动转换成int。之后再次转换为Integer。
你可能感兴趣的文章
初识Spring(IOC,DI,创建流程)
查看>>
初识Spring Framework——Bean、注册Bean、依赖注入
查看>>
思维导图模式 -- 深度理解及复习 网络 知识
查看>>
SpringBoot使用Redis做缓存,RedisUtil
查看>>
为什么你们这么喜欢在for循环里面增删改查!
查看>>
JAVA -敏感词过滤器 工具类SensitiveFilter
查看>>
JAVA 订单号生成类
查看>>
JAVA - 根据用户自增ID生成邀请码的工具类
查看>>
VUE中父子页面传值,子页面调用父页面方法
查看>>
Element-ui Cascader 级联选择器回显数据
查看>>
js字符串数组转数字数组及map方法函数的用法
查看>>
JAVA路径拼接File.separator
查看>>
JAVA给网站添加爬虫数据-超简单(jsoup)新闻图片数据
查看>>
linux安装nodejs
查看>>
@JsonFormat时间误差的坑,相差8小时
查看>>
Linux将服务设置为开机自启,linux启动VUE项目,设置VUE项目自启
查看>>
JAVA中判断数据不为空后执行数据操作、防止空指针报错的工具类,safes工具类
查看>>
TypeError: Cannot read property ‘parseComponent‘ of undefined解决办法-VUE
查看>>
kingbase逻辑备份报错解决-sys_dump:
查看>>
java8-Stream流的介绍\创建\基本操作\
查看>>