包装类

包装类间的关系

自动装箱和自动拆箱

JDK1.5以后,基础类型和包装类可以自动转换

自动装箱:基本->包装 ; 调用 包装类.valueOf(基本类型)
自动拆箱:包装->基本 ; 调用 **Value()

自动拆装箱的原理

自动调用方法转换

自动装箱: Integer.valueOf(1)

1
2
Integer integer=1;
Integer integer=Integer.valueOf(1);

自动拆箱: integer.intValue();

1
2
int i=integer;
int i=integer.intValue();

触发自动拆装箱

除了直接赋值以外,其它的触发方式

函数参数与返回值

1
2
3
4
5
6
7
8
//自动拆箱
public int getNum1(Integer num) {
return num;
}
//自动装箱
public Integer getNum2(int num) {
return num;
}

包装类型和基本类型的 运算

包装类与基本数据类型进行比较运算,是先将包装类进行拆箱成基本数据类型,然后进行比较的。

1
2
3
4
Integer a=1;
System.out.println(a==1?"等于":"不等于");
Boolean bool=false;
System.out.println(bool?"真":"假");

对以上代码进行反编译,得到以下代码:

1
2
3
4
Integer a=1;
System.out.println(a.intValue()==1?"等于":"不等于");
Boolean bool=false;
System.out.println(bool.booleanValue?"真":"假");

包装类型的 四则运算

对Integer对象进行四则运算的时候,两个包装类型之间的运算,会被自动拆箱成基本类型进行。

1
2
3
4
Integer i = 10;
Integer j = 20;

System.out.println(i+j);

反编译后代码如下:

1
2
3
Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());

基本数据类型放入集合类

Java中的集合类只能接收对象类型

1
2
3
4
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i ++){
li.add(i);
}

将上面代码进行反编译,可以得到以下代码:

1
2
3
4
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i += 2){
li.add(Integer.valueOf(i));
}

以上,我们可以得出结论,当我们把基本数据类型放入集合类中的时候,会进行自动装箱。

三目运算符的使用

三目运算符:

1
2
3
4
boolean flag = true;
Integer i = 0;
int j = 1;
int k = flag ? i : j;

在int k = flag ? i : j;这一行,会发生自动拆箱。反编译后代码如下:

1
2
3
4
boolean flag = true;
Integer i = Integer.valueOf(0);
int j = 1;
int k = flag ? i.intValue() : j;

这其实是三目运算符的语法规范:当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。

因为例子中,flag ? i : j;片段中,第二段的i是一个包装类型的对象,而第三段的j是一个基本类型,所以会对包装类进行自动拆箱。如果这个时候i的值为null,那么久会发生NPE。(自动拆箱导致空指针异常)

缓存

包装类与基础类型的对应关系及其缓存范围

自动装箱时,即使用Integer.valueOf(40)时,会触发缓存机制,在缓存范围内的直接指向缓存地址
而使用 new Integer(40) 创建新对象时,始终会创建新对象而不使用缓存

使用 == 比较两个包装类,比较的是地址,比较结果在缓存范围内外会不一致。

比较两个包装类不使用 == , 使用 equals(obj) 。而 equals 比较的始终是具体值,需注意包装类的空指针异常