解读java的包装类

Java是面向对象语言,在她的世界里充满了对象,对象让我们更好地彼此沟通,但是在java中有一块区域是不具备对象特性的,就是基本数据类型(boolean,byte,short,character,int,long,double,float),为了能让基本数据类型也具备对象的特性,Java为每个基本类型提供了包装类,如int的包装类Integer。这样我们就可以像操作对象那样来操作基本数据类型,如利用toString,pasreInt来进行类型转换。另外包装类带来的好处是允许在集合类(list,HashMap)来操作基本数据类型。

在JDK5.0之前是不允许直接将基本数据类型的数据直接赋值给其对应地包装类的,如:

[java] 
  1. Integer i = 5;  

但是在JDK5.0中支持这种写法,因为编译器会自动将上面的代码转换成如下代码:

[java] 
  1. Integer i=Integer.valueOf(5);  

这就是Java的装箱,由此会产生一个很有意思的现象:

[java] 
  1. Integer i1 =5;  
  2. Integer i2 =5;  
  3.   
  4. Integer i3 =500;  
  5. Integer i4 =500;  
  6.   
  7. System.out.println(i1 == i2);   // true  
  8.   
  9. System.out.println(i3 == i4);   // false   

为什么这两个输出地结果会是不一样的呢,首先我们要从Java的自动装箱说起,自动装箱时调用的valueOf(int)方法的源码如下:

[java] 
  1.  public static Integer valueOf(int i) {  
  2.     final int offset = 128;  
  3.     if (i >= -128 && i <= 127) { // must cache   
  4.         return IntegerCache.cache[i + offset];  
  5.     }  
  6.       return new Integer(i);  
  7.  }  
  8.   
  9.   
  10. private static class IntegerCache {  
  11.   
  12.       
  13.   
  14. private IntegerCache(){}  
  15. static final Integer cache[] = new Integer[-(-128) + 127 + 1];  
  16.     static {  
  17.         for(int i = 0; i < cache.length; i++)  
  18.         cache[i] = new Integer(i - 128);  
  19.     }  
  20. }  

从上面的代码我们可以清晰地看到当 i>=-128 && i<=127时方法返回的IntegerCache中的cache数组的值,cache数组则是存储在缓存中,这样做的目的是为了提高性能,当你大量使用new Integer(5)时就不用大量地创建对象实例,而是共用cache数组已经创建好的Integer对象实例,这也是享元模式的体现(String类是通过字符串常量池来实现的)。

与装箱对应地,JDK5.0提供了自动拆箱,代码如下:

[java] 
  1. Integer i =5;  
  2. int j = i;  
 第一行先进行自动装箱,生成Integer对象实例 i,再把 i 赋值给 int类型的 j 时,编译器会做如下操作:
[java] 
  1. int j = i.intValue();  
把 i 的int类型数值赋值给 j,这样就完成了自动拆箱的过程。Java的拆箱也产生了一个比较有意思的情况,如:

[java] 
  1.  Integer i1=new Integer(5);  
  2.  Integer i2=new Integer(5);  
  3.   
  4. System.out.println((i1!=i2)&&(i1<=i2)&&(i1>=i2)); // true  
解释起来也很简单,i1 != i2比较的是两个对象的引用,而i1 <= i2和i1 >= i2比较的是拆箱之后的基本数据类型的数值。

装箱和拆箱在重载中的应用,如下:

[java] 
  1. public class Test{  
  2.      public static void main(String[] a) {  
  3.          int i = 5;  
  4.          print(i);  
  5.      }  
  6.   
  7.      public static void print(Integer i) {  
  8.          System.out.print("Integer");  
  9.      }  
  10.   
  11.      public static void print(long l) {  
  12.          System.out.print("long");  
  13.      }  
  14.  }  

上面输出“long”,也就是说编译器选择了对 i 进行加宽操作,让 int 类型的 i 转换成 long类型,而不是对 i 进行装箱为 Integer,故加宽>装箱,那var-arg(可变参数列表)呢,如果你去测试会发现装箱>var-arg。

说到这里我们基本上已经介绍完了Java的包装类已经相关地自动装拆箱,在更好地了解了包装类以及自动装拆箱之后,有助于我们日常开发中的代码优化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值