`
xiaolongfeixiang
  • 浏览: 236807 次
  • 性别: 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 解惑里面有相关的题目,楼主非常清楚的解释了一遍

相关推荐

    jdk5_64.zip

    JDK5引入了自动装箱和拆箱机制,使得基本类型与包装类之间的转换变得无缝且高效,提升了编程的便利性。 四、变长参数(Varargs) JDK5引入的变长参数,允许方法接收可变数量的参数,形式为`public void methodType...

    jdk5 win7 64位

    - **自动装箱/拆箱(Autoboxing and Unboxing)**:自动装箱将基本类型与对应的包装类之间进行转换,简化了代码。 - **可变参数(Varargs)**:允许在方法声明中使用可变长度的参数列表,方便调用。 - **增强的...

    JDK5免安装解压包

    3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱和拆箱简化了基本类型与包装类之间的转换。这意味着开发者不再需要手动进行如Integer i = new Integer(5); 这样的操作,而是可以直接写成Integer i = 5;...

    jdk5 64位exe文件.zip

    3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱是指将基本类型与对应的包装类之间进行自动转换,而自动拆箱则是相反的过程。这一特性简化了代码,使得处理基本类型和它们的包装类更加方便。 4. **...

    JDK1.5、JDK5下载

    2. **自动装箱与拆箱(Autoboxing/Unboxing)**:自动装箱允许在基本类型和对应的包装类之间进行无缝转换,简化了代码编写。 3. **枚举类型(Enums)**:枚举是一种新的数据类型,用于定义有限集合的常量,提高了...

    JDK 5中文文档PDF文档JDK 5中文文档PDF文档

    3. **自动装箱/拆箱(Autoboxing and Unboxing)**:自动装箱允许在原始类型与对应的包装类之间无缝转换,简化了代码。例如,`Integer i = 5;` 会自动将int转换为Integer对象,而 `int j = i;` 又会自动将Integer...

    jdk5 windows 32位.rar

    2. **Autoboxing/Unboxing**:自动装箱和拆箱功能,使得基本类型与对应的包装类之间可以无缝转换。 3. **枚举类型(enum)**:增强了枚举的使用,使其成为一种强大的数据类型,支持比较、遍历等操作。 4. **变量作用...

    良葛格JDK5学习笔记

    但JDK5引入了自动装箱(Autoboxing)和拆箱(Unboxing)机制,使得在基本类型与对象之间转换变得更加方便。例如,`Integer i = 10;`会自动将int值装箱为Integer对象,而`int j = i;`则会自动拆箱。 二、枚举类型...

    jdk5.0 资源下载

    2. 自动装箱/拆箱(Autoboxing and Unboxing):自动装箱允许基本数据类型与对应的包装类之间进行无缝转换,简化了代码,提高了编写效率。 3. 枚举类型(Enums):JDK5.0引入了枚举类型,使得常量的定义更加规范,...

    包含 jdk1.5免安装、jdk1.6免安装、jdk1.8(32和64)

    2. **Autoboxing/Unboxing(自动装箱/拆箱)**:简化了基本类型与对应的包装类之间的转换。 3. **枚举(Enums)**:提供了一种新的数据类型,用于创建固定的、不可变的值集合。 4. **Annotations(注解)**:提供了...

    jdk1.5(jdk-1_5_0_08-windows-i586-p.exe)

    3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱和拆箱简化了基本类型与对应的包装类之间的转换,使得代码更加简洁。 4. **变量注解(Varargs)** 通过使用`...`操作符,可以定义接受任意数量参数的...

    jdk-1_5_0_22-windows-amd64

    6. **类型安全的异构容器(Autoboxing and Unboxing)**:集合框架可以包含任何类型的对象,但JDK 1.5引入了类型安全的异构容器,如`Collections.synchronizedList()`,它们可以自动处理基本类型和包装类之间的转换...

    jdk1.5 x86

    JDK5中引入了自动装箱和拆箱功能,使得基本数据类型与对应的包装类之间可以无缝转换,简化了代码编写,提高了开发效率。 3. **枚举类型(Enums)** 在JDK5之前,Java中的常量通常使用public static final变量来...

    jdk-1_5_0_22-windows-i586-p

    3. **自动装箱/拆箱(Autoboxing and Unboxing)** 自动装箱允许开发者在基本数据类型与对应的包装类之间无缝转换,简化了代码。例如,`Integer i = 5;`会自动将int值装箱成Integer对象,而`int j = i;`则会自动...

    jdk5特性总结PPT

    2. **自动装箱与拆箱(Autoboxing/Unboxing)** 自动装箱允许基本数据类型与对应的包装类之间自动转换,减少了手动转换的工作量,提高了代码的简洁性。例如,`Integer i = 10;` 和 `int x = i;` 都能自动进行装箱和...

    jdk-1_5_0-windows

    3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱允许开发者在原始类型和其对应的包装类之间进行无缝转换。例如,int与Integer之间的转换无需手动调用`Integer.valueOf()`或`.intValue()`方法。 4. **...

    jdk5新特性

    JDK 5.0,也称为Java 2 Platform, Standard Edition 5 (J2SE 5),是Java历史上的一个重要里程碑,它引入了一系列创新特性和改进,显著提升了开发效率和程序性能。下面将详细介绍JDK 5中的主要新特性。 1. **泛型...

    jdk1.5.0-21

    3. **自动装箱/拆箱(Autoboxing and Unboxing)** 自动装箱是指将基本类型自动转换为对应的包装类对象,而拆箱则是反过来的过程。这个特性简化了代码,让开发者在处理基本类型和包装类对象之间转换时无需手动进行...

    jdk1.4绿色免安装版

    4. **自动装箱与拆箱(Autoboxing and Unboxing)**: 自动装箱使得基本类型与对应的包装类之间可以无缝转换,减少了手动装箱和拆箱的繁琐操作。 5. ** assert 关键字**: `assert`关键字用于编写单元测试,帮助...

    jdk1.5绿色版

    2. **自动装箱/拆箱(Autoboxing and Unboxing)**:1.5版本引入了自动装箱和拆箱机制,使得基本数据类型和其对应的包装类之间可以无缝转换,简化了编程。 3. **枚举类型(Enums)**:JDK1.5开始支持枚举类型,使得...

Global site tag (gtag.js) - Google Analytics