管中窥虎
在学习java 1.5的过程中,我使用了sun公布的tutorial,这份文档写的比较详尽易明,但是对于想快速了解tiger而且具有较好java基础的人来说,大篇幅的英文文档是比较耗时间和非必需的,所以我将会归纳这份文档的主要内容,在保证理解的底线上,尽力减少阅读者需要的时间。
在以下地址可以进入各新增语言特色介绍以及下载相关文档(若有)。
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html
2006年8月15日星期二
第三道虎纹:自动包装机制
我们知道容器类不能放基本类型的,放进放出都要先包装和解包,所有的这些工作都是繁琐而无聊的,它早就该有自动机制了,终于在
1.5
里得到了实现。
import
java.util.
*
;
//
Prints a frequency table of the words on the command line
public
class
Frequency
{
public
static
void
main(String[] args)
{
Map
<
String, Integer
>
m
=
new
TreeMap
<
String, Integer
>
();
for
(String word : args)
{
Integer freq
=
m.get(word);
m.put(word, (freq
==
null
?
1
: freq
+
1
));
}
System.out.println(m);
}
}
java Frequency if it is to be it is up to me to do the watusi
{be=1, do=1, if=1, is=2, it=2, me=1, the=1, to=3, up=1, watusi=1}
注意到
freq
如果为空,那么
put
的第二个参数就是
int
类型的
1
,这个时候就出现了自动的包装,而如果
freq
不为空,那么
freq
+
1
就是自动解包后运算,再自动包装,放入
Map
中。
现在你基本上可以忽略
Integer
和
int
(或者这一类的对应)之间的区别了,除了要注意几点警告:
Integer
是可以为
null
的,如果程序试图自动解包一个
null
,会抛出
NullPointerException
。
==用于
Integer
时比的是引用,用于
int
的时候比的是值。最后,还有一点就是即使现在是自动解包打包,它们的运行损耗并没消失,你依然为这些动作付出了
cpu
的计算时间。
这里还有一个相关的例子:
//
List adapter for primitive int array
public
static
List
<
Integer
>
asList(
final
int
[] a)
{
return
new
AbstractList
<
Integer
>
()
{
public
Integer get(
int
i)
{
return
a[i]; }
//
Throws NullPointerException if val == null
public
Integer set(
int
i, Integer val)
{
Integer oldVal
=
a[i];
a[i]
=
val;
return
oldVal;
}
public
int
size()
{
return
a.length; }
}
;
}
通过自动的包装机制,提供了数组与
List
的灵活转换,但是它的运行效率是比较低的,每个
get
,
set
操作,都进行了解包或者打包,偶尔使用这个方法还凑合,如果是用于核心代码的循环里,那就是够傻的了。
那我们什么时候该用自动的包装机制呢?仅仅是用于消除这类所谓的“阻抗不匹配”,就是基本类型与包装类的差异,例如要把数值放入容器类的时候。如果在进行科学计算的代码或者其他讲究效率的代码中使用,则是不恰当的。一个
Integer
不是一个
int
,自动包装机制仅仅模糊了它们的区别,而没有消除之。