Java学习之理解自动拆装箱特性

一、自动装拆箱是什么?
  • 有时,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类,例如 Integer类对应基本类型int。通常,这些类被称为包装器。

  • 这些包装类对应基本数据类型:

    Integer , Long , Float , Short , Byte, Charater , Boolen;

    (前六个类派生于公共的超类Number)

  • 包装类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值,同时,包装类还是final,因此不能派生他的子类。

二、拆装箱的使用
1.引入包装类的原因:
  1. 包装成对象后更加方便操作,比如可以直接封装一些方法放在类中方便使用:比如,将一个数字字符串s转换成数值 可以使用:int x = Integer.parseInt(s)
  2. 或者能方便将数据加入集合:假如想要定义一个整型数组列表。遗憾的是,尖括号中的类型参数不允许是基本类型,也就是说,不允许写成如 ArrayList,这里就可以用到Integer 包装类。

    我们可以声明一个Integer对象的数组列表:

    ArrayList list = new ArrayList()

注:由于每个值分别包装在对象中,所以ArrayList的执行效率远低于int[ ]数组。因此,只有当操作的方便性比执行效率更重要时,才会考虑对较小的集合使用这种构造

2.自动拆装箱的运用
  1. 对于向ArrayList()中添加int类型的元素 就可以用到自动装箱的特性,下面这个调用:

    list.add(3);

    将自动变换成:

    list.add(Integer.valueOf(3));

    这就是 自动装箱(autoboxing)

  2. 相反的 当将一个Integer对象赋给一个int值时,将会自动拆箱。也就是说,编译器将以下语句:

    int n=list.get(i);

    转换成:

    int n =list.get(i).intValue();

    这就是 自动拆箱

3.一些典型举例
  1. 自动拆装箱适用于算术表达式。例如,可以将自增运算符应用于包装类引用:

    Integer n =1;

    n++;

    编译器将自动插入一条对象拆箱的指令,然后进行自增运算,最后再将结果拆箱。

  2. ==运算符和包装类联用的注意

    (以下内容谈到了 运行时常量池,如果需要搞清楚请移步这篇文章)

(1)自动装箱常见的就是valueOf这个方法,自动拆箱就是intValue方法。在它们的源码中有一段代码定义了包装类的缓冲区。除了两个包装类Long和Double 没有实现这个缓存技术,其它的包装类均实现了它。

如下代码:

Integer i1 = 40;
Integer i2 = 40;
Double i3 = 40.0;
Double i4 = 40.0;

System.out.println("i1=i2   " + (i1 == i2));
System.out.println("i3=i4   " + (i3 == i4));

-----结果----
true
false

原理如下:

“==” 这个运算在不出现算数运算符的情况下 不会自动拆箱,所以i1 和 i 2它们不是数值进行的比较,仍然是比较地址是否指向同一块内存,在integer源码中缓冲区的范围是-128-127之间,在此范围内只要不new对象,那么数值的地址都是相同的,都在常量池区域。而Double没有设置缓冲区,自然i3 i4的地址不相同。

所以包装类对象比较时最好调用equals方法。

  1. (1)由于包装类引用可以为NULL,所以自动装箱有可能会抛出一个NullPointerException异常:

    eg:Integer n =null; System.out.println(2*n);

    (2)另外,如果在一个条件表达式中混合使用Integer和Double类型,Integer值会拆箱,提升为double再装箱为Double;

    引用--《java核心技术卷一》
收藏 (0)
评论列表
正在载入评论列表...
我是有底线的
为您推荐
    暂时没有数据