Java 作为一门面向对象的语言,仍然保留了基本的几种值类型(int,short,long,byte,char,boolean,float,double)。当然为了方便开发人员使用也提供了对应的包装类,(Integer,Short,Long,Byte,Char,Boolean,Float,Double),并且在 Java 1.5 中开始提供了自动装箱(boxing)和拆箱(unboxing)特性。

自动装箱的主要作用是方便在值类型和包装类型之间切换,比如可以直接在源代码里将值类型赋值给包装类型或反之,使用 == 来比较值类型和包装类型的值。这里提到是源代码里这样做是因为自动装箱/拆箱特性主要由编译器帮我们完成。

当我们编写以下一段程序时

1
2
3
int a = new Integer(5);
Integer b = 6;
assert(a == b);
  • 其中第一行代码需要将包装类型赋值给值类型,编译器会生成等效于 int a = new Integer(5).intValue(); 的代码
  • 对于第二行,则有 Integer b = Integer.valueOf(6);
  • 而对于值类型与包装类型的比较,则会先将包装类型转为基本类型,即 assert(a.intValue() == b);

关于包装类型的缓存
根据 Java 语言规范(JLS8,§5.1.7),包装类型会对部分值做缓存,在像 Integer.valueOf(int) 这样的方法中起作用,所以会出现 Integer a = 5; Integer b = 5; assert(a == b); 的情况。

If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between ‘\u0000’ and ‘\u007f’ inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.