装箱和拆箱:
- 装箱:基本类型转换成包装类型,使用的是 valueOf() 方法
- 拆箱:包装类型转换成基本类型,使用的是 intValue(),longValue(),… 方法
自动拆箱引发的空指针:
- 变量赋值自动拆箱出现空指针
- 方法传参时自动拆箱出现空指针 ```java public static int add(int x, int y) { return x + y; }
public static void main(String[] args) { // 1.变量赋值自动拆箱出现空指针 Long count = null; long count_ = count;
// 2.方法传参时自动拆箱引发的空指针
Integer left = null;
Integer right = null;
add(left, right);
}
基本类型和包装类型的区别:<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/750131/1602133342434-5d6af081-8c4a-43c3-abd5-4bbc21051ff8.png#align=left&display=inline&height=202&margin=%5Bobject%20Object%5D&name=image.png&originHeight=247&originWidth=668&size=89450&status=done&style=none&width=547)<br />注意事项:
- Integer 包装类中有个静态内部类 IntegerCache,用于缓存 -128 到 127(默认)的Integer 实例,通过 valueOf 方法能够看到,再次创建值在 -128 到 127 区间的 Integer实例时,会复用缓存中的实例,也就是直接指向缓存中的 Integer 实例(这里的创建不包括使用 new 创建,new 创建会直接创建新对象)
```java
// 直接使用字面量,会调用 Integer.valueOf() 进行包装,即-128到127的Integer从缓存池中获取
Integer a = 128;
Integer b = 128;
a == b; // false
Integer c = 127;
Integer d = 127;
c == d; // true
// new
Integer e = new Integer(127);
Integer f = new Integer(127);
e == f; // false
// 在基本类型和包装类型进行比较时,包装类会拆箱,比较的是值
int a = 127;
Integer b = 127;
Integer c = new Integer(127);
a == b; // true
a == c; // true
Byte、Short、Integer、Long、Character也具有缓存机制。其中 Byte,Short,Integer,Long为 -128 到 127,Character范围为 0 到 127。如 Long 类中的缓存类源码:
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
// 通过静态代码中完成缓存的初始化,即在类生命周期的初始化阶段执行
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
Integer 的缓存上界可以通过 jvm 参数 -XX:AutoBoxCacheMax=size 指定,除此之外,其他的缓存不能更改
规避自动拆箱引发空指针的建议:
- 对于不确定的包装器类型,一定要校验是否为 NULL
- 对于变量的属性,优先使用包装类型,方便统一判断,即 xxx != null