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 .
 
程序首先声明一个 String Integer map 来关联命令行中每个单词出现在次数。然后遍历每个单词。程序在 map 中查找每个单词,然后把修改过的 entry 放入 map 中。绿色高亮显示的代码既包含自动装箱又包含自动出箱。为了计算与每个单词相关联的新值,首先程序查看当前值,如果它是 null 的话,此时是该单词第一次出现的情况,在 map 中放入 1 。否则就在前次出现的次数基础上加 1 ,然后再放到 map 中去。当然,您既可能把 int 放入 map 中,也不可能把 1 加到 Integer 上去。到底发生了什么呢?为了使 freq 1 ,程序自动进行出箱,产生一个 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.
 
这样您就可以忽略 int Integer 间的区分,只是会有一些警告。整型可包含 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.
 
结果链表的性能可能是很差的,因为每一个 get set 操作都执行了出箱或装箱。对于间歇性的使用它是足够快的,但在内循环中会严重影响性能。
 
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 的替代品;自动装箱和出箱使基本型和引用类型间的区别变得模糊起来,但并没有消除。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值