一、自动装拆箱是什么?
- 有时,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类,例如 Integer类对应基本类型int。通常,这些类被称为包装器。
-
这些包装类对应基本数据类型:
Integer , Long , Float , Short , Byte, Charater , Boolen;
(前六个类派生于公共的超类Number) - 包装类是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值,同时,包装类还是final,因此不能派生他的子类。
二、拆装箱的使用
1.引入包装类的原因:
包装成对象后更加方便操作,比如可以直接封装一些方法放在类中方便使用:比如,将一个数字字符串s转换成数值 可以使用:int x = Integer.parseInt(s)或者能方便将数据加入集合:假如想要定义一个整型数组列表。遗憾的是,尖括号中的类型参数不允许是基本类型,也就是说,不允许写成如 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 没有实现这个缓存技术,其它的包装类均实现了它。
如下代码:
1
2
3
4
5
6
|
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方法。
3.(1)由于包装类引用可以为NULL,所以自动装箱有可能会抛出一个NullPointerException异常:
eg:Integer n =null; System.out.println(2*n);
(2)另外,如果在一个条件表达式中混合使用Integer和Double类型,Integer值会拆箱,提升为double再装箱为Double;
引用--《java核心技术卷一》
以上就是java学习之理解自动拆装箱特性的详细内容,更多关于java自动拆装箱的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/qq_51964402/article/details/120289742