体验J2SE 1.5新特性之装箱和拆箱
2008-01-05 20:02:51 来源:WEB开发网核心提示:J2SE 1.5提供了“Autoboxing”和“Auto-Unboxing”的机制,可以让编译器来自动完成在基本类型和它们的包裹对象之间的转化工作,体验J2SE 1.5新特性之装箱和拆箱,从而能够用一种更简单的方式,来避免同时存在两套类型系统所带来的一些麻烦,是J2SE 1.5中新加入的内容,其它包裹类也都有可以接受
J2SE 1.5提供了“Autoboxing”和“Auto-Unboxing”的机制,可以让编译器来自动完成在基本类型和它们的包裹对象之间的转化工作,从而能够用一种更简单的方式,来避免同时存在两套类型系统所带来的一些麻烦。
本文介绍Autoboxing/Auto-Unboxing机制的使用方法、实质、发生时机、局限、对重载机制的影响以及对性能的妨碍等问题。
传统上,在java程序中,可以往一个容器类(无论是Collection还是Map)里直接放入一个对象;但是假如打算放入的是一个数字、字符或布尔值的话,就要先加入一个“生成包裹它们的对象”的步骤。
造成这种现象的原因是,在Java语言当中一直存在着两套非常不同的类型系统:
一套是所谓的“引用类型”(Reference Types),包括所有的类和接口。这些类型的数据被看作对象,所以可以用一个Object型的变量来保存。
一套是所谓的“基本类型”(PRimitive Types),包括:byte、short、int、long、float、double、char和boolean。这些类型的数据不是对象,因此也不能用Object型的变量来保存。
同时采用这样两套类型系统,可以得到一些性能方面的好处——因为基本类型的数据不是对象,所以创建得更快、占用的空间更少、收回它们占用的资源也更轻易;但是,这样的做法同时也会造成一些编码方面的问题——例如,不能定义一个变量(或数组),让它既能保存基本类型的数据,又能保存引用类型的数据(类似的,也不能定义一个同时能匹配这两种类型的数据的形参,不过这个问题可以借助Java里的重载机制往返避)。
实际上需要定义“不知道用来保存什么类型的数据”的变量(和形参)时,一般对这个问题采取回避的态度,将它们的类型定义成Object,然后借助可以称为“Boxing”和“Unboxing”的操作来解决Object不能涵盖基本类型的问题。
1. Boxing和Unboxing操作
所谓Boxing操作,是指通过生成一个能包裹基本类型数据的对象,来让基本类型的数据出现在只能接受引用类型的地方。
清单1:手工Boxing的典型情况
Collection integers = new ArrayList();
for(int i = 0; i < 10; i++) {
integers.add(new Integer(i));
}
用于生成这些的对象的类,被称作“包裹类”(Wrapper Classes)。Java中的包裹类有Byte 、Short、Integer、Long、Float、Double、Character和Boolean(都在java.lang包里定义)等八种,分别用于包裹byte、short、int、long、float、double、char和boolean类型的数据。
而所谓Unboxing操作,则是指调用包裹类对象的相应方法,得到它们所代表的“基本类型的数据”,以便进行进一步的处置。
清单2:手工Unboxing的典型情况
for(Iterator itr = integers.iterator(); itr.hasNext(); ) {
Integer i = (Integer) itr.next();
System.out.println(i.intValue() + 1);
}
而在Java语言的最新版本——J2SE 1.5中,提供了“Autoboxing”和“Auto-Unboxing”的机制,可以让编译器来自动完成这些琐碎的操作,从而用一种更简单的方式,来整合两套类型系统。
熟悉的生疏名词
尽管这一对操作的历史很悠久,但是把它们称作“Boxing”和“Unboxing”的做法,基本是在出现“Autoboxing”和“Auto-Unboxing”的概念之后,才得到了广泛的接受。在那之前,它们似乎并没有通用的、专门的名字。不过由于那时也很少提及这两个概念,所以这个问题倒也没有造成什么严重的影响。
2. 使用Autoboxing和Auto-Unboxing
使用Autoboxing和Auto-Unboxing,并不需要什么非凡的步骤,一切都会在编译器的安排下自动发生。
现在可以这样来对待一个int型的数据:
清单3:自动完成的Boxing操作
Collection al = new ArrayList();
al.add(1);
因为编译器会静静的把这段代码转换成接近这个样子:
清单4:作了Autoboxing之后的等价形式
Collection al = new ArrayList();
al.add(Integer.valueOf(1));
这里所用的能接受int类型的值为参数,生成Integer实例的valueOf方法,是J2SE 1.5中新加入的内容。其它包裹类也都有可以接受对应的基本类型的值为参数,生成对应的包裹类实例的valueOf方法加入。
而这样对待一个Integer型的对象也是可以的:
清单5:自动完成的Unboxing操作
Integer one = new Integer(1);
int two = one + 1;
传统上,在java程序中,可以往一个容器类(无论是Collection还是Map)里直接放入一个对象;但是假如打算放入的是一个数字、字符或布尔值的话,就要先加入一个“生成包裹它们的对象”的步骤。
造成这种现象的原因是,在Java语言当中一直存在着两套非常不同的类型系统:
一套是所谓的“引用类型”(Reference Types),包括所有的类和接口。这些类型的数据被看作对象,所以可以用一个Object型的变量来保存。
一套是所谓的“基本类型”(PRimitive Types),包括:byte、short、int、long、float、double、char和boolean。这些类型的数据不是对象,因此也不能用Object型的变量来保存。
同时采用这样两套类型系统,可以得到一些性能方面的好处——因为基本类型的数据不是对象,所以创建得更快、占用的空间更少、收回它们占用的资源也更轻易;但是,这样的做法同时也会造成一些编码方面的问题——例如,不能定义一个变量(或数组),让它既能保存基本类型的数据,又能保存引用类型的数据(类似的,也不能定义一个同时能匹配这两种类型的数据的形参,不过这个问题可以借助Java里的重载机制往返避)。
实际上需要定义“不知道用来保存什么类型的数据”的变量(和形参)时,一般对这个问题采取回避的态度,将它们的类型定义成Object,然后借助可以称为“Boxing”和“Unboxing”的操作来解决Object不能涵盖基本类型的问题。
1. Boxing和Unboxing操作
所谓Boxing操作,是指通过生成一个能包裹基本类型数据的对象,来让基本类型的数据出现在只能接受引用类型的地方。
清单1:手工Boxing的典型情况
Collection integers = new ArrayList();
for(int i = 0; i < 10; i++) {
integers.add(new Integer(i));
}
用于生成这些的对象的类,被称作“包裹类”(Wrapper Classes)。Java中的包裹类有Byte 、Short、Integer、Long、Float、Double、Character和Boolean(都在java.lang包里定义)等八种,分别用于包裹byte、short、int、long、float、double、char和boolean类型的数据。
而所谓Unboxing操作,则是指调用包裹类对象的相应方法,得到它们所代表的“基本类型的数据”,以便进行进一步的处置。
清单2:手工Unboxing的典型情况
for(Iterator itr = integers.iterator(); itr.hasNext(); ) {
Integer i = (Integer) itr.next();
System.out.println(i.intValue() + 1);
}
而在Java语言的最新版本——J2SE 1.5中,提供了“Autoboxing”和“Auto-Unboxing”的机制,可以让编译器来自动完成这些琐碎的操作,从而用一种更简单的方式,来整合两套类型系统。
熟悉的生疏名词
尽管这一对操作的历史很悠久,但是把它们称作“Boxing”和“Unboxing”的做法,基本是在出现“Autoboxing”和“Auto-Unboxing”的概念之后,才得到了广泛的接受。在那之前,它们似乎并没有通用的、专门的名字。不过由于那时也很少提及这两个概念,所以这个问题倒也没有造成什么严重的影响。
2. 使用Autoboxing和Auto-Unboxing
使用Autoboxing和Auto-Unboxing,并不需要什么非凡的步骤,一切都会在编译器的安排下自动发生。
现在可以这样来对待一个int型的数据:
清单3:自动完成的Boxing操作
Collection al = new ArrayList();
al.add(1);
因为编译器会静静的把这段代码转换成接近这个样子:
清单4:作了Autoboxing之后的等价形式
Collection al = new ArrayList();
al.add(Integer.valueOf(1));
这里所用的能接受int类型的值为参数,生成Integer实例的valueOf方法,是J2SE 1.5中新加入的内容。其它包裹类也都有可以接受对应的基本类型的值为参数,生成对应的包裹类实例的valueOf方法加入。
而这样对待一个Integer型的对象也是可以的:
清单5:自动完成的Unboxing操作
Integer one = new Integer(1);
int two = one + 1;
- ››体验Win8 OneNote 高效率大功能
- ››体验Discuz! X1.5搜索新变革 挖掘内容更方便
- ››体验简单分析 如何做好用户体验
- ››体验Photoshop CS5新增的HDR色调调整
- ››体验 iphone 的越狱和解码功能
- ››体验 Jazz,体验 Rational Team Concert Express
- ››体验 Spring 的 Object/XML 映射支持
- ››体验ASP.NET4之ClientID
- ››体验Windows Server 2008 R2的RemoteApp
- ››体验Illustrator的旋转和缩放工具
- ››体验风行给你的三个非主流功能
- ››体验Photoshop CS4的三维能力
更多精彩
赞助商链接