1.装箱与拆箱
● 定义
(1)装箱:将基本数据类型用对应的引用类型包装起来
(2)拆箱:将包装类型转换为对应基本数据类型
● 示例
Integer i = 10; //装箱
int n = i; //拆箱
●数据类型和对应包装器
int(4字节) | Integer |
byte(1字节) | Byte |
short(2字节) | Short |
long(8字节) | Long |
float(4字节) | Float |
double(8字节) | Double |
char(2字节) | Character |
boolean(未定) | Boolean |
● 自动封箱和拆箱
自动装箱都是通过包装类的valueOf()
方法来实现的.自动拆箱都是通过包装类对象的xxxValue()
来实现的。
自动装箱原理
//原码
public static void main(String[]args){
Integer integer=1; //装箱
int i=integer; //拆箱
}
//反编译后
public static void main(String[]args){
Integer integer=Integer.valueOf(1);
int i=integer.intValue();
}
● 问题
(1)不同数据类型下封箱的==判断
当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)
public class Main {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); //true
System.out.println(i3==i4); //false
}
}
public class Main {
public static void main(String[] args) {
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2);//false
System.out.println(i3==i4);//false
}
}
Integer情况:
原因:为什么会出现这样的结果?输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。此时只需一看源码便知究竟。在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
Double情况:
原因:在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。Double的valueOf创建新对象。
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}
注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Double、Float的valueOf方法的实现是类似的。
引用:深入学习java源码之Double.parseDouble()与Double.valueOf()
(2)谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。
当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:
1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;
2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。
(3)下面程序的输出结果是什么?
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d); //true
System.out.println(e==f); //false--超过127
System.out.println(c==(a+b)); //true
System.out.println(c.equals(a+b)); //true
System.out.println(g==(a+b)); //true
System.out.println(g.equals(a+b)); //false
//g.equals(i)执行时,i被转为某种对象类型后,被equals()方法参数obj引用,if (obj instanceof Long)测试失败,所以直接return false; (a+b)为Integer对象
System.out.println(g.equals(a+h));//true; h是long,a+h后转为long型
}
}
这里面需要注意的是:当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换
包装类型的运算:
Integer i = 10;
Integer j = 20;
System.out.println(i+j);
//反编译后
Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());
//自动拆箱 转换成基本类型进行运算