`
sabolasi
  • 浏览: 915016 次
文章分类
社区版块
存档分类
最新评论

Autoboxing(自动装箱)

 
阅读更多
As any Java programmer knows, you can’t put an int (or other primitive value) into a collection. Collections can only hold object references, so you have to box primitive values into the appropriate wrapper class (which is Integer in the case of int). When you take the object out of the collection, you get the Integer that you put in; if you need an int, you must unbox the Integer using the intValue method. All of this boxing and unboxing is a pain, and clutters up your code. The autoboxing and unboxing feature automates the process, eliminating the pain and the clutter.
每个Java程序员都知道,不可能把一个int(或其它基本类型的值)放入一个collection中去。集合只能存放对象的引用,所以您必须把基本类型值装箱成适合的包装类(int对应的包装类是integer)。当您想从集合中取出对象时,您获取的是您放入的Integer;如果您需要的是一个int,您就必须用intValue方法。装箱出箱是一件很痛苦的事情,也把代码弄得乱糟糟的。自动装箱出箱特性使这一过程变得自动化,消除这种痛苦,并可以保持代码整洁。
The following example illustrates autoboxing and unboxing, along with generics and the for-each loop. In a mere ten lines of code, it computes and prints an alphabetized frequency table of the words appearing on the command line.
下面的例子演示了自动装箱和出箱,同时也用到了范型和for-each循环。在仅有的十行代码中,计算并按字母顺序打印出命令行中每个单词的出现频率。
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}
The program first declares a map from String to Integer, associating the number of times a word occurs on the command line with the word. Then it iterates over each word on the command line. For each word, it looks up the word in the map. Then it puts a revised entry for the word into the map. The line that does this (highlighted in green) contains both autoboxing and unboxing. To compute the new value to associate with the word, first it looks at the current value (freq). If it is null, this is the first occurrence of the word, so it puts 1 into the map. Otherwise, it adds 1 to the number of prior occurrences and puts that value into the map. But of course you cannot put an int into a map, nor can you add one to an Integer. What is really happening is this: In order to add 1 to freq, it is automatically unboxed, resulting in an expression of type int. Since both of the alternative expressions in the conditional expression are of type int, so too is the conditional expression itself. In order to put this int value into the map, it is automatically boxed into an Integer.
程序首先声明一个StringIntegermap来关联命令行中每个单词出现在次数。然后遍历每个单词。程序在map中查找每个单词,然后把修改过的entry放入map中。绿色高亮显示的代码既包含自动装箱又包含自动出箱。为了计算与每个单词相关联的新值,首先程序查看当前值,如果它是null的话,此时是该单词第一次出现的情况,在map中放入1。否则就在前次出现的次数基础上加1,然后再放到map中去。当然,您既可能把int放入map中,也不可能把1加到Integer上去。到底发生了什么呢?为了使freq1,程序自动进行出箱,产生一个int类型的表达式。因为在条件表达式两边都是int类型,条件表达式自身也当然是。为了能把int类型值放入map,程序自动地把它装箱成Integer
The result of all this magic is that you can largely ignore the distinction between int and Integer, with a few caveats. An Integer expression can have a null value. If your program tries to autounbox null, it will throw a NullPointerException. The == operator performs reference identity comparisons on Integer expressions and value equality comparisons on int expressions. Finally, there are performance costs associated with boxing and unboxing, even if it is done automatically.
这样您就可以忽略intInteger间的区分,只是会有一些警告。整型可包含null值。如果您的程序试图把一个null值出箱,就会抛出一个NullPointerException异常。对于Integer类型==操作符进行引用的比较,而对于int类型,进行值的比较。最后要提一下,即使装箱出箱是自动完成的,也是有很大的性能损耗的。
Here is another sample program featuring autoboxing and unboxing. It is a static factory that takes an int array and returns a List of Integer backed by the array. In a mere ten lines of code this method provides the full richness of the List interface atop an int array. All changes to the list write through to the array and vice-versa. The lines that use autoboxing or unboxing are highlighted in green:
这里还有一个用到装箱出箱的程序。接收一个int类型数组并返回Integer类型链表。在十几行代码中,这个方法提供从数组到链表的丰富内容。绿色高亮部分是装箱出箱:
// 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; }
};
}
The performance of the resulting list is likely to be poor, as it boxes or unboxes on every get or set operation. It is plenty fast enough for occasional use, but it would be folly to use it in a performance critical inner loop.
结果链表的性能可能是很差的,因为每一个getset操作都执行了出箱或装箱。对于间歇性的使用它是足够快的,但在内循环中会严重影响性能。
So when should you use autoboxing and unboxing? Use them only when there is an “impedance mismatch” between reference types and primitives, for example, when you have to put numerical values into a collection. It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate it.
那什么时候该使用自动装箱和出箱呢?仅在引用类型和基本型间出现了“类型不匹配”错误时才用,例如,当您必须把一个数值型放入一个集合中去时。在使用科学计数法或其它敏感性数字代码中不宜使用自动装箱和出箱。Integer并不是int的替代品;自动装箱和出箱使基本型和引用类型间的区别变得模糊起来,但并没有消除。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics