之前在项目中,遇到一个Integer转int出现NullPointException的问题,导致无法开机,记录一下
示例代码如下:
HashMap<String,Integer> typeMap = new HashMap<String,Integer>();
typeMap.put("one",1);
int value = typeMap.get("two");
原因很清楚,当Integer为空的时候,转换成Int会调用Integer.intValue方法,所以出现空指针
1.关于封装类的一些理解
因为Java语言中,primtive types和Generic(泛型)不能混用,所以引入 autoBoxing和unBoxing,提供了primtive types和class types隐式转换
- autoBoxing:将一个基础类型的值改变成封装类的过程(如Integer.valueOf())。Java编译器会在如下2个场景将基础类型包装为Object
- 基础类型值作为方法的参数,预期的传入是一个封装Object
- 将基础类型值赋值给封装类
- unBoxing:Integer转Int,Java编译器会调用Integer.intValue,返回一个int值
Integer是int的封装类,自动封装和解封装都是在Java编译器里面处理的,其中的过程通过代码显示如下:
Integer integer = 1;
int value = integer;
上面的代码通过反编译javap -c xxx.class文件
#1 = Methodref #14.#56 // java/lang/Object."<init>":()V
#2 = Methodref #44.#57 // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
#3 = Methodref #44.#58 // java/lang/Integer.intValue:()I
2.Java中类型的说明
以下内容摘自JSL CHAPTER 4 Types, Values, and Variables文档
Java是一种静态语言,在编译的时候,所有变量和表达式都有自己的类型
Java也是一种强类型语言,因为类型限制了变量和表达式的值,限制可以执行的operations,可以减少编译时的错误
Java语言支持的类型分为2类:primtive types(基础类型)和refernce types(引用类型).
- primtive types是指boolean 类型和数字类型,其中数字类型又分为整型(包括byte、short、int、long和char)和浮点型(float、double).换句话我们熟悉的话来说是,8种基础类型包括boolean、float、double、byte、short、int、long和char
- refernce types:有3种class types (类), interface types (接口), and array types (数组).
3.关于Integer的一些理解
Integer的值,注意是final类型的,也就是说创建对象后,这个值不能再发生变化
// Integer的值
private final int value
equals方法是比的value值
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer 类提供了其它类型转Integer的方法
- public Integer(String s)
- public Integer(int value)
- Integer valueOf(int i)
也提供了Integer转其它类型的方法
- byteValue
- shortValue
- intValue
- longValue
- floatValue
- doubleValue
- toString
内部类IntegerCache是实现了JSL 5.1.7 Boxing Conversion里面的定义,通过缓存节约内存和提高性能,可以通过 JVM 参数来设置
-XX:AutoBoxCacheMax=size
当创建Integer对象的时候,如果有缓存(范围是 [-128, 127]),则直接取缓存的结果,否则创建一个新的Integer对象
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
加深一下理解 ,看如下代码的输出
Integer integer1 = 3;
Integer integer2 = 3;
System.out.println("integer1 == integer2 is " + (integer1 == integer2));
Integer integer3 = 128;
Integer integer4 = 128;
System.out.println("integer3 == integer4 is " + (integer3 == integer4));
Integer integer5 = new Integer(3);
Integer integer6 = new Integer(3);
System.out.println("integer5 == integer6 is " + (integer5 == integer6));
输出结果是,原因是IntegerCache只缓存了-128到127之间的值,所以integer1和integer2是用的同一个缓存对象,integer3和integer4是2个不同的对象
integer1 == integer2 is true
integer3 == integer4 is false
integer5 == integer6 is false
注意:
IntegerCache只适用于autoboxing
参考: