写在前面:
这是一个老生常谈的话题。本文只适合初学者!!
什么是自动装箱(AutoBoxing)?
官方文档:
http://java.sun.com/j2se/1.5.0/docs/guide/language/autoboxing.html
简单地翻一下,献丑了。\(^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的字节码文件:
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
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 中。
总结:
那么什么时候使用自动装箱(autoboxing)和自动拆卸(unboxing)呢?仅当在引用类型(也即是包装类)与原生数据类型之间存在 “阻抗失谐”时,比如你想将一个数值 放入到 collection中。在科学计算或者其他性能要求高的数字计算中,是不适合使用自动装箱(autoboxing)和自动拆卸(unboxing)。自动装箱(autoboxing)和自动拆卸(unboxing)模糊了原生数据类型与引用类型之间的区别,但是并没有完全消除这种差别。
相关推荐
JDK5引入了自动装箱和拆箱机制,使得基本类型与包装类之间的转换变得无缝且高效,提升了编程的便利性。 四、变长参数(Varargs) JDK5引入的变长参数,允许方法接收可变数量的参数,形式为`public void methodType...
- **自动装箱/拆箱(Autoboxing and Unboxing)**:自动装箱将基本类型与对应的包装类之间进行转换,简化了代码。 - **可变参数(Varargs)**:允许在方法声明中使用可变长度的参数列表,方便调用。 - **增强的...
3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱和拆箱简化了基本类型与包装类之间的转换。这意味着开发者不再需要手动进行如Integer i = new Integer(5); 这样的操作,而是可以直接写成Integer i = 5;...
3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱是指将基本类型与对应的包装类之间进行自动转换,而自动拆箱则是相反的过程。这一特性简化了代码,使得处理基本类型和它们的包装类更加方便。 4. **...
2. **自动装箱与拆箱(Autoboxing/Unboxing)**:自动装箱允许在基本类型和对应的包装类之间进行无缝转换,简化了代码编写。 3. **枚举类型(Enums)**:枚举是一种新的数据类型,用于定义有限集合的常量,提高了...
3. **自动装箱/拆箱(Autoboxing and Unboxing)**:自动装箱允许在原始类型与对应的包装类之间无缝转换,简化了代码。例如,`Integer i = 5;` 会自动将int转换为Integer对象,而 `int j = i;` 又会自动将Integer...
2. **Autoboxing/Unboxing**:自动装箱和拆箱功能,使得基本类型与对应的包装类之间可以无缝转换。 3. **枚举类型(enum)**:增强了枚举的使用,使其成为一种强大的数据类型,支持比较、遍历等操作。 4. **变量作用...
但JDK5引入了自动装箱(Autoboxing)和拆箱(Unboxing)机制,使得在基本类型与对象之间转换变得更加方便。例如,`Integer i = 10;`会自动将int值装箱为Integer对象,而`int j = i;`则会自动拆箱。 二、枚举类型...
2. 自动装箱/拆箱(Autoboxing and Unboxing):自动装箱允许基本数据类型与对应的包装类之间进行无缝转换,简化了代码,提高了编写效率。 3. 枚举类型(Enums):JDK5.0引入了枚举类型,使得常量的定义更加规范,...
2. **Autoboxing/Unboxing(自动装箱/拆箱)**:简化了基本类型与对应的包装类之间的转换。 3. **枚举(Enums)**:提供了一种新的数据类型,用于创建固定的、不可变的值集合。 4. **Annotations(注解)**:提供了...
3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱和拆箱简化了基本类型与对应的包装类之间的转换,使得代码更加简洁。 4. **变量注解(Varargs)** 通过使用`...`操作符,可以定义接受任意数量参数的...
6. **类型安全的异构容器(Autoboxing and Unboxing)**:集合框架可以包含任何类型的对象,但JDK 1.5引入了类型安全的异构容器,如`Collections.synchronizedList()`,它们可以自动处理基本类型和包装类之间的转换...
JDK5中引入了自动装箱和拆箱功能,使得基本数据类型与对应的包装类之间可以无缝转换,简化了代码编写,提高了开发效率。 3. **枚举类型(Enums)** 在JDK5之前,Java中的常量通常使用public static final变量来...
2. **自动装箱与拆箱(Autoboxing/Unboxing)** 自动装箱允许基本数据类型与对应的包装类之间自动转换,减少了手动转换的工作量,提高了代码的简洁性。例如,`Integer i = 10;` 和 `int x = i;` 都能自动进行装箱和...
3. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱允许开发者在原始类型和其对应的包装类之间进行无缝转换。例如,int与Integer之间的转换无需手动调用`Integer.valueOf()`或`.intValue()`方法。 4. **...
JDK 5.0,也称为Java 2 Platform, Standard Edition 5 (J2SE 5),是Java历史上的一个重要里程碑,它引入了一系列创新特性和改进,显著提升了开发效率和程序性能。下面将详细介绍JDK 5中的主要新特性。 1. **泛型...
4. **自动装箱与拆箱(Autoboxing and Unboxing)**: 自动装箱使得基本类型与对应的包装类之间可以无缝转换,减少了手动装箱和拆箱的繁琐操作。 5. ** assert 关键字**: `assert`关键字用于编写单元测试,帮助...
2. **自动装箱/拆箱(Autoboxing and Unboxing)**:1.5版本引入了自动装箱和拆箱机制,使得基本数据类型和其对应的包装类之间可以无缝转换,简化了编程。 3. **枚举类型(Enums)**:JDK1.5开始支持枚举类型,使得...
3. **自动装箱/拆箱(Autoboxing and Unboxing)**:Java 1.5引入了自动装箱和拆箱机制,使得基本类型和对应的包装类之间可以无缝转换,简化了代码编写。 4. **变量赋值增强(Enhanced for Loop)**:也称为foreach...
2. **自动装箱与拆箱(Autoboxing and Unboxing)** 自动装箱允许开发者在原始类型与对应的包装类之间无缝切换,无需手动进行转换。例如,`int`与`Integer`之间的转换可以自动完成。 3. **枚举类型(Enums)** ...