Java装箱与拆箱

Java装箱与拆箱

​ Java是一种纯面向对象语言,但是java中有8种基本数据类型,破坏了java为纯面向对象的特征。为了承诺在java中一切皆对象,java又给每种基本数据类型分别匹配了一个类,这个类我们称之为包装类。

注意:每个基本数据类型都有一个与之匹配的包装类。

基本数据类型与其包装类

包装类的层次结构:

数据的装箱和拆箱

装箱和拆箱

  • 装箱:把基本数据类型包装为对应的包装类对象 

    int a = 10;
    Integer i1 = new Integer(a);  // 利用构造方法
    Integer i2 = Integer.valueOf(a); //利用包装类中的静态方法
  • 拆箱:把包装类对象转换为对应的基本数据类型。

    Integer i1 = new Integer(10);
    int b = i1.intValue();  //返回包装类对象i1对应的基本数据

自动装箱和自动拆箱

​ 上面的装箱和拆箱操作,相对较麻烦。自jdk1.5开始,java增加的对基本数据类型的自动装箱和自动拆箱操作。java编译器在编译时期会根据源代码的语法来决定是否进行装箱或拆箱。

  1. 自动装箱:可以直接把一个基本数据类型赋值给包装类,例如:

    int a = 3 ;
    Integer b = a;  //自动装箱操作
  2. 自动拆箱:可以直接把一个包装类对象,赋值给基本类型,例如:

    Integer a = new Integer(3); 
    int b = a;//自动拆箱。

自动装箱和自动拆箱,简化了对包装类的操作。

自动装箱和自动拆箱 源码篇

我们都知道,使用 == 运算符是比较内存地址,每个对象的内存地址都是JVN计算出来的唯一且不相等的。

来看下面的案例:

案例一:

Integer i = new Integer(120);//都是通过new 地址唯一
Integer j = new Integer(120);//都是通过new 地址唯一
System.out.println(i==j);
// 这里  i ==j 结果肯定是false。

案例二:

Integer i = 120;// 通过自动装箱 值在 byte取值范围内
Integer j = 120;// 通过自动装箱 值在 byte取值范围内
System.out.println(i==j);
// 这里  i ==j 结果是true。

案例三:

Integer i = 128;// 通过自动装箱 值在 超过byte取值范围
Integer j = 128;// 通过自动装箱 值在 超过byte取值范围
System.out.println(i==j);
// 这里  i ==j 结果又是false。

这是为什么呢?

事实上,int基本数据类型的包装过程是调用了 Integer.valueOf(int i) 的方法进行包装的。

public final class Integer extends Number implements Comparable<Integer> {
    ……//代码省略

    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++);// 看这里....当该类IntegerCache被使用时,会缓存256个Integer对象,[-128,127]。
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }
        private IntegerCache() {}
    }
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)//当通过valueOf 装箱int值时,如果在byte值取值范围内,则直接返回缓存的Integer对象。
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);//超过byte的返回则一律使用new创建。
    }
  ……//代码省略
}

那么通过观察 Integer.valueOf(int i) 方法的源码我们不难发现。

当通过valueOf 装箱int值时,如果在byte值取值范围内,则直接返回缓存的Integer对象。

所以在开发当中装箱方式推荐使用 Integer.valueOf(int i)方式装箱,或直接使用自动装箱即可(自动装箱默认执行Integer.valueOf(int i))。

提示:其他基本数据类型 类似!可自行观察源码学习!!!

你可能感兴趣的:(JAVA,SE,java,面向对象,包装类)