自动装箱与拆箱
概念
自动装箱:就是自动将基本数据类型包装为包装器类型;
自动拆箱:就是自动将包装器类型转换为基本数据类型;
1 | Interger i = 1; // 拆箱 |
这个装箱拆箱操作是jdk5的新特性
- JDK5之前的方式:比如Integer i = Integer.valueof(5);(这里5为基本类型int,Integer包装类利用valueof()方法将其转换为Integer类型)或者int i = i.intValue();(这里基本类型利用intValue()方法将Integer类型转换为基本类型int)。
- JDK5之后的方式:比如①Integer i = 5;或者②int i = new Integer(100);,这里基本类型与包装类之间可直接操作,而①的操作就是自动装箱,②的操作就是自动拆箱。
| More Actions 默认值 | 存储需求(字节) | 取值范围 | 示例 | 包装类型 | |
|---|---|---|---|---|---|
| byte | 0 | 1 | -2^7—2^7-1 | byte b=10; | Byte |
| char | ‘ \u0000′ | 2 | 0—2^16-1 | char c=’c’ ; | Character |
| short | 0 | 2 | -2^15—2^15-1 | short s=10; | Short |
| int | 0 | 4 | -2^31—2^31-1 | int i=10; | Integer |
| long | 0 | 8 | -2^63—2^63-1 | long o=10L; | Long |
| float | 0.0f | 4 | -2^31—2^31-1 | float f=10.0F | Float |
| double | 0.0d | 8 | -2^63—2^63-1 | double d=10.0; | Double |
| boolean | false | 不确定 | true\false | boolean flag=true; | Boolean |
boolean的大小java规范并没有明确给出具体查看:
例题
1、有如下4条语句:()
1 | Integer i01=59; |
以下输出结果为false的是:
- System.out.println(i01==i02);
- System.out.println(i01==i03);
- System.out.println(i03==i04);
- System.out.println(i02==i04);
解析:
- 无论如何,Integer与new Integer不会相等。不会经历拆箱过程。
- 两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false;java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存。
Integer.valueOf方法中也有判断,如果传递的整型变量>= -128并且小于127时会返回IntegerCache类中一个静态数组中的某一个对象, 否则会返回一个新的Integer对象,代码如下
1
2
3
4
5
6 public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.[i + (-IntegerCache.low)];
return new Integer(i);
}
- 两个都是new出来的,都为false
- int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比
我认为理论看的再多也不如实际的去做题,理论知道的多,题目不一定做得对,做题可以巩固自己的理论知识。
2、下面程序的输出结果是什么?(这个是我引用参考链接中第二个链接中的一个例子)
1 | public class Main { |
解析:
- c==d:因为Integer中缓存的存在,如果数在[-128,127] (包括边界),则是true,否则为false
- e==f:同1
- c=(a + b):a + b 这个操作会自动拆箱结果为int
- c.equals(a+b):无需解释
- (g==(a+b)):同3 a+b=> int g为Long自动拆箱为long 然后int类型自动提升为long
- g.equals(a+b):a+b 为int 类型,Long 与 相同值的 包装类 用equals比较时,如果传入的类型不是Long,那么全部返回false,Long类中的equals()源码:
- g.equals(a+b):true a+h 结果会向精度大的转换 为long类型
总结
比较值
- 基本数据类型与引用数据类型进行比较时,引用数据类型会进行拆箱,然后与基本数据类型进行值的比较
int i = 12;
Integer j = new Integer(12);
i == j 返回的是true
二、引用数据类型与基本数据类型进行比较(equals方法),基本数据类型会进行自动装箱,与引用数据类型进行比较,Object中的equals方法比较的是地址,但是Integer类已经重写了equals方法,只要两个对象的值相同,则可视为同一对象,具体看API文档,所以这归根到底也是值的比较!
int i = 12;
Integer j = new Integer(12);
j.equals(i) 返回的是true
比较地址
- 如果引用数据类型是这样 Integer i = 12;直接从常量池取对象,这是如果数值是在-128与127之间,则视为同一对象,否则视为不同对象
Integer i = 12; Integer j = 12; i == j 返回的是true
Integer i = 128; Integer j = 128; i == j 返回的是false
- 如果引用数据类型是直接new的话,不管值是否相同,这时两个对象都是不相同的,因为都会各自在堆内存中开辟一块空间
Integer i =new Integer(12);
Integer j = new Integer(12);
i == j 这时返回的是false
- 从常量池取对象跟new出来的对象也是不同的
举例:
Integer i = 12; // 这个常量池中的
Integer j = new Integer(12) // 这个是堆中创建的
i == j 这时返回的是false
参考
https://www.cnblogs.com/wang-yaz/p/8516151.html
https://www.cnblogs.com/dolphin0520/p/3780005.html
这两篇文章从源码以及jvm分析了原理,并且写的很好,我就不再说明了。



