Java装箱与拆箱

装箱拆箱详解
今天面试,遇到了这个问题,不注意,答错了。回顾一下相关java知识。
装箱:将基本数据类型包装成引用数据类型,使其具有对象的性质。
拆箱:将引用型数据简化成基本数据类型。
举个例子:
Integer a=4;自动装箱
int b=new Integer(4);自动拆箱
为了进一步说明问题,写段代码。

public class DataType {

    public static void main(String args[]) {
        DataType dt = new DataType();
        dt.m1();
        dt.m2();
        dt.m3();
        dt.m4();
        dt.m5();
        dt.m6();
        dt.m7();
        dt.m8();

    }

    public void m1() {
        Integer a = new Integer(4);
        Integer b = 4;
        System.out.println("m1 result " + (a == b));
    }

    public void m2() {
        Integer a = new Integer(128);
        Integer b = 128;
        System.out.println("m2 result " + (a == b));
    }

    public void m3() {
        Integer a = new Integer(4);
        Integer b = new Integer(4);
        System.out.println("m3 result " + (a == b));
    }

    public void m4() {
        Integer a = new Integer(128);
        Integer b = new Integer(128);
        System.out.println("m4 result " + (a == b));
    }

    public void m5() {
        Integer a = 4;
        Integer b = 4;
        System.out.println("m5 result " + (a == b));
    }

    public void m6() {
        Integer a =128;
        Integer b =128;
        System.out.println("m6 result " + (a == b));
    } 

     public void m7() {
        Integer a = Integer.valueOf(4);
        Integer b = 4;
        System.out.println("m7 result " + (a == b));
    }

    public void m8() {
        Integer a = Integer.valueOf(128);
        Integer b = 128;
        System.out.println("m8 result " + (a == b));
    } 


}

分析一下执行结果吧。

下面给出打印结果。你是否都对了呢?

运行结果

我们来看一下。

第一组:
观察 m1,m2。
a和b是两个不同的对象,不难看出,上面两组都是false。

第二组:
观察m3,m4。
a和b 依旧是两个不同的对象。都为false。

第三组
观察m5,m6。
为什么一个true,一个false呢?

第四组
观察m7,m8。
为什么一个true,一个false呢?
true说明a和b是同一个对象。a通过Integer.valueOf()生成,b通过自动装箱生成。为什么会是同一个对象呢?下面为false又是怎么回事?

为说明问题,回顾一下装箱、拆箱的两个方法:
Integer.valueOf()返回一个Integer类型对象。
Integer.parseInt()返回一个int类型对象。
查看valueOf方法实现,代码如下:


/**
 * Returns a <tt>Integer</tt> instance representing the specified
 * <tt>int</tt> value.
 * If a new <tt>Integer</tt> instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Integer(int)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * @param  i an <code>int</code> value.
 * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
 * @since  1.5
 */
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache 
    return IntegerCache.cache[i + offset];
}
    return new Integer(i);
}

发现,[-128,127]区间的数据返回的是缓冲区中的对象,其他则是新创建的装箱对象。这就解释得通了。为进一步说明问题,这里看一下IntegerCache的源码:

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

对于这个例子,也可以使用javap解析字节码查看:

f:\>javap -c DataType
Compiled from "DataType.java"
public class DataType {
  public DataType();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class DataType
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4                  // Method m1:()V
      12: aload_1
      13: invokevirtual #5                  // Method m2:()V
      16: aload_1
      17: invokevirtual #6                  // Method m3:()V
      20: aload_1
      21: invokevirtual #7                  // Method m4:()V
      24: aload_1
      25: invokevirtual #8                  // Method m5:()V
      28: aload_1
      29: invokevirtual #9                  // Method m6:()V
      32: aload_1
      33: invokevirtual #10                 // Method m7:()V
      36: aload_1
      37: invokevirtual #11                 // Method m8:()V
      40: return

  public void m1();
    Code:
       0: new           #12                 // class java/lang/Integer
       3: dup
       4: iconst_4
       5: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
       8: astore_1
       9: iconst_4
      10: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: astore_2
      14: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      17: new           #16                 // class java/lang/StringBuilder
      20: dup
      21: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      24: ldc           #18                 // String m1 result
      26: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: aload_1
      30: aload_2
      31: if_acmpne     38
      34: iconst_1
      35: goto          39
      38: iconst_0
      39: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      42: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      45: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      48: return

  public void m2();
    Code:
       0: new           #12                 // class java/lang/Integer
       3: dup
       4: sipush        128
       7: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
      10: astore_1
      11: sipush        128
      14: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      17: astore_2
      18: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      21: new           #16                 // class java/lang/StringBuilder
      24: dup
      25: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      28: ldc           #23                 // String m2 result
      30: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      33: aload_1
      34: aload_2
      35: if_acmpne     42
      38: iconst_1
      39: goto          43
      42: iconst_0
      43: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      46: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      49: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      52: return

  public void m3();
    Code:
       0: new           #12                 // class java/lang/Integer
       3: dup
       4: iconst_4
       5: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
       8: astore_1
       9: new           #12                 // class java/lang/Integer
      12: dup
      13: iconst_4
      14: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
      17: astore_2
      18: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      21: new           #16                 // class java/lang/StringBuilder
      24: dup
      25: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      28: ldc           #24                 // String m3 result
      30: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      33: aload_1
      34: aload_2
      35: if_acmpne     42
      38: iconst_1
      39: goto          43
      42: iconst_0
      43: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      46: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      49: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      52: return

  public void m4();
    Code:
       0: new           #12                 // class java/lang/Integer
       3: dup
       4: sipush        128
       7: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
      10: astore_1
      11: new           #12                 // class java/lang/Integer
      14: dup
      15: sipush        128
      18: invokespecial #13                 // Method java/lang/Integer."<init>":(I)V
      21: astore_2
      22: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      25: new           #16                 // class java/lang/StringBuilder
      28: dup
      29: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      32: ldc           #25                 // String m4 result
      34: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      37: aload_1
      38: aload_2
      39: if_acmpne     46
      42: iconst_1
      43: goto          47
      46: iconst_0
      47: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      50: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      53: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      56: return

  public void m5();
    Code:
       0: iconst_4
       1: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       4: astore_1
       5: iconst_4
       6: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       9: astore_2
      10: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      13: new           #16                 // class java/lang/StringBuilder
      16: dup
      17: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      20: ldc           #26                 // String m5 result
      22: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      25: aload_1
      26: aload_2
      27: if_acmpne     34
      30: iconst_1
      31: goto          35
      34: iconst_0
      35: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      38: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      41: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      44: return

  public void m6();
    Code:
       0: sipush        128
       3: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: astore_1
       7: sipush        128
      10: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: astore_2
      14: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      17: new           #16                 // class java/lang/StringBuilder
      20: dup
      21: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      24: ldc           #27                 // String m6 result
      26: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: aload_1
      30: aload_2
      31: if_acmpne     38
      34: iconst_1
      35: goto          39
      38: iconst_0
      39: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      42: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      45: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      48: return

  public void m7();
    Code:
       0: iconst_4
       1: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       4: astore_1
       5: iconst_4
       6: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       9: astore_2
      10: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      13: new           #16                 // class java/lang/StringBuilder
      16: dup
      17: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      20: ldc           #28                 // String m7 result
      22: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      25: aload_1
      26: aload_2
      27: if_acmpne     34
      30: iconst_1
      31: goto          35
      34: iconst_0
      35: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      38: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      41: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      44: return

  public void m8();
    Code:
       0: sipush        128
       3: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       6: astore_1
       7: sipush        128
      10: invokestatic  #14                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: astore_2
      14: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
      17: new           #16                 // class java/lang/StringBuilder
      20: dup
      21: invokespecial #17                 // Method java/lang/StringBuilder."<init>":()V
      24: ldc           #29                 // String m8 result
      26: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: aload_1
      30: aload_2
      31: if_acmpne     38
      34: iconst_1
      35: goto          39
      38: iconst_0
      39: invokevirtual #20                 // Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
      42: invokevirtual #21                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      45: invokevirtual #22                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      48: return
}

总结:
以Integer为例,说明。
1.使用new Integer()方式装箱每次创建的对象都不同。对于任何数值,即使数值相同,它们也是不同的对象。
2.对于自动装箱,其实是调用了Integer.valueOf()。对于使用这种方式装箱的对象,在[-128,127]之间的数据会优先使用缓冲区中的对象,如果数值相同,它们是同一个对象。在此区间外,即使是同一数值也是不同的对象。
3.使用new Integer()方式装箱,两者无论数值相同与否,都是不同对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值