`
xiaolongfeixiang
  • 浏览: 234623 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

也谈JDK5的自动装箱(AutoBoxing)

阅读更多

写在前面:

 

  这是一个老生常谈的话题。本文只适合初学者!!

 


什么是自动装箱(AutoBoxing)?

 

官方文档:

 

http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html

 

写道
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).

 

简单地翻一下,献丑了。\(^o^)/~

 

所有的Java程序员都知道的,不能把一个int(或者其他的原生数据类型的值)放入一个colletion中。collection中只能放置对象的引用,所以必须把原生数据类型包装(box)成相应的包装类。(比如,Integer是int的包装类)

 

举个例子:

List list = new ArrayList();

//list.add(1) // 这在JDK5之前,是不可以的。

list.add(new Integer(1))  // 只能这样写

 

(我开始学Java已经是JDK6了,没体验过这种情况。⊙﹏⊙b)

 

 

有了JDK5的autoboxing呢,你就可以这样了:

// 使用了JDK5的泛型。可以简单的理解为,是对List中元素类型的约束!
List<Integer> list = new ArrayList<Integer>();

list.add(1);  // 写着方便多了吧  O(∩_∩)O~

 

 

自动装箱是怎么回事?

 

肯定是编译器的优化,那编译器是怎么做的呢?

 

package tiger;
public class AutoBox {
	{
		Integer i = 15;
	}
}

 

检查一下AutoBox.class的字节码文件:

 
public tiger.AutoBox();
Code:
Stack=1, Locals=2, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: bipush 15
6: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: astore_1
10: return
LineNumberTable:
line 2: 0
line 4: 4
line 5: 10

 

第6行,可以发现,编译器编译时,在class中加入了Integer.valueOf()方法。也就相当于:

package tiger;
public class AutoBox {
	{
		Integer i = Integer.valueOf(15);
	}
}

 

    Integer.valueOf(int i) 的 JDK源码( JDK6 update16)。

    public static Integer valueOf(int i) {
        if(i >= -128 && i <= IntegerCache.high)
            return IntegerCache.cache[i + 128];
        else
            return new Integer(i);
    }

 自动装箱的性能问题

 

从上述叙述中,知道了自动装箱,其实是编译器在背后做了工作,即在class中加入了Integer.valueOf方法。

 

如果代码中存在大量的 自动装箱的需要,就会比较浪费效率。

 

然而在上述JDK源码的valueOf中,可以发现,JVM对Integer做了缓存(cache)。缓存的范围是 -128 到 IntegerCache.high.

 

让我们更进一步看看:

 

JDK的IntegerCache源码:

 

 private static class IntegerCache {
        static final int high;
        static final Integer cache[];

        static {
            final int low = -128;

            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                     // 得到系统参数integerCacheHighPropValue的值
                int i = Long.decode(integerCacheHighPropValue).intValue();
                     // 指定的参数不能小于127,否则会设为127
                i = Math.max(i, 127);
                     
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }

                 //  127=< high <=Integer.MAX_VALUE-128 
            high = h;
                 //  填充满Integer缓存
            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

 

JVM默认缓存了-128 -- 127 之间的所有的Integer。有了缓存之后,就可以降低自动装箱对性能的影响了。

 

缓存带来的问题(比较无聊的问题) o(︶︿︶)o

 

public class T {
	
	public static void main(String[] agrs){
		int i = 128;
		int j = 128;
		System.out.println(i==j);
		
		Integer a = 126;
		Integer b = 126;
		System.out.println(a==b);

		Integer one = 128;
		Integer two = 128;
		System.out.println(one == two);
		
	}
}
输出
true
true
false

 

    分别解释:

 

     i -- j 组:

 

      2个普通的原生数据类型。比较的是128 == 128 (当然相等了),输出true;

 

    a -- b 组:

 

     存在自动装箱,因此JVM在运行时调用Integer.valueOf方法,上文提到JVM默认缓存了-128 -- 127 之间的所有的Integer。所以a 、b都是对缓存中的Integer(126)的引用。所以输出true。

 

    one -- two 组:

 

      存在自动装箱,因此JVM在运行时调用Integer.valueOf方法,但是128不在缓存的范围内,Integer.valueOf接着调用new Interger(128)的方法,所以相当于:

 

 

Integer one = new Integer(128);
Integer two = new Integer(128);

     当然返回false了。

 

   PS:这种缓存问题还存在于 Byte Character Long Short 中。

 

 

总结:

 

官方的建议:
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.

 

   那么什么时候使用自动装箱(autoboxing)和自动拆卸(unboxing)呢?仅当在引用类型(也即是包装类)与原生数据类型之间存在 “阻抗失谐”时,比如你想将一个数值 放入到 collection中。在科学计算或者其他性能要求高的数字计算中,是不适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。自动装箱(autoboxing)和自动拆卸(unboxing)模糊了原生数据类型与引用类型之间的区别,但是并没有完全消除这种差别。

 

 

 

3
1
分享到:
评论
9 楼 xiaolongfeixiang 2013-01-21  
shiznet 写道
singlePad 写道
引用
It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code.

引用
在科学计算或者其他性能要求高的数字计算中,是适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。

楼主解释的很清楚 有处翻译个人觉得有些出入


恩,同感觉对性能要求高的地方就不适用auto-boxing


已改正,谢谢关注!
8 楼 xiaolongfeixiang 2013-01-21  
singlePad 写道
引用
It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code.

引用
在科学计算或者其他性能要求高的数字计算中,是适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。

楼主解释的很清楚 有处翻译个人觉得有些出入


嗯,翻译的时候少打个字。好久不上JavaEye了,怎么变成ITeye了。。
7 楼 shiznet 2012-07-03  
singlePad 写道
引用
It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code.

引用
在科学计算或者其他性能要求高的数字计算中,是适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。

楼主解释的很清楚 有处翻译个人觉得有些出入


恩,同感觉对性能要求高的地方就不适用auto-boxing
6 楼 我是坏蛋 2011-12-27  
不错,,,学习了,
5 楼 singlePad 2011-09-26  
引用
It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code.

引用
在科学计算或者其他性能要求高的数字计算中,是适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。

楼主解释的很清楚 有处翻译个人觉得有些出入
4 楼 xiaolongfeixiang 2010-05-25  
beneo 写道
我没有其它意思,让你误会了


呵呵,谢谢你来看博客,并留言。
3 楼 beneo 2010-05-25  
我没有其它意思,让你误会了
2 楼 xiaolongfeixiang 2010-05-24  
引用
Java 解惑里面有相关的题目,楼主非常清楚的解释了一遍


呵呵,声明这篇文章确实是本人原创,只参考了sun的官方说明,然后自己反编译的时候发现的。没有参考其他文章。
1 楼 beneo 2010-05-24  
Java 解惑里面有相关的题目,楼主非常清楚的解释了一遍

相关推荐

Global site tag (gtag.js) - Google Analytics