如你所知,Java使用基本类型(如int或double)来保存该语言支持的基本数据类型.使用基本类型而不是对象是出于性能的考虑.如果对于这些基本类型使用对象,对于那怕最简单的计算都会带来不可接受的开销.因此,基本类型不属于对象层次结构,他们不继承Object.
尽管使用基本类型有性能上的优势,但是有时还是需要使用对象表示.例如,不能通过方法的应用来传递简单类型.而且,许多Java实现的标准数据结构都是对象,这意味着不能使用这些数据结构来保存基本类型.为了处理这些(和其他一些)情况,Java提供了类型封装器(typeWrapper),他们是一些在对象中封装基本类型的类.
类型封装器有Double,Float,Long,Interger,Short,Byte,Character和Boolean,他们包含在Java.lang中.这些类提供了各种方法将基本类型完整的集成到Java的对象层次结构中.
可能最常用的类型封装器是那些代表数值的封装器,他们是Byte,Short,Integer,Long,Float和Double.这些数值类型封装器都继承自抽象类Number.Number声明了以不同的数值类型返回对象值的方法.这些方法如下所示:
byte byteValue() double doubleValue() float floatValue() int intValue() long longValue() short shortValue()
例如,doubleValue()返回double类型的对象值,floatValue()返回float类型的对象值.这些方法都由各自的数值类型封装器实现.
这些数值类型封装器都定义了允许从给定值或表示该值的字符串来构造对象的构造函数.例如,下面是为Integer和Double定义的构造函数.
Integer(int num) Integer(String str) throws NumberFormatException Double(double num) Double(String str) throws NumberFormatException
如果str没有包含有效的数值,将抛出NumberFormatException异常.
所有的类型封装器都重写了toString(),他以人们可读的形式返回包含在封装器的值.这样做允许通过把类型封装器对象传递给println()来输出值,而不必把他转换为基本类型.
把值封装在对象中的过程称为装箱(boxing),在JDK5之前,装箱都是手工进行的,由程序员显式构造一个带有所需值的封装器实例.例如,下面的语句手工把值100装箱为Integer:
Interger iOb = new Integer(100)
在本例中,显式新建了一个值为100的Integer对象,并且把该对象的引用赋给iOb.
从类型封装器提取值的过程称为拆箱(unboxing),在JDK5之前,拆箱也是手工完成的,程序员需要显式调用一个封装器的方法来获得其值.例如,下面的语句手工把iOb中的值拆箱到int:
int i = iOb.intValue();
其中,intValue()把封装在iOb中的值返回为int.
下面的程序演示了前面的概念:
public static void main(String args[]) { Integer iOb = new Integer(100); int i = iOb.intValue(); System.out.println(i+" "+iOb); }
这个程序将数值100封装在一个名为iOb的Integer对象中.然后,程序通过调用intValue()获得这个值,并将其存储在i中.最后,程序显示了i和iOb的值,两者均为100.
在JDK5之前的所有Java版本中,手工装箱和拆箱的一般步骤都与前面的示例一样,而且这种做法在遗留的许多代码中仍然广泛使用着.问题在于,由于这种做法需要程序员手工创建用于封装值的对象,以及在需要其值的时候显式获得合适的基本类型,所以这种方法及枯燥,又容易出错.幸好,自动装箱/拆箱从根本上改变了这些步骤.