Java基础——自动装箱与拆箱

自动装箱与拆箱

  • 装箱:将基本类型用包装器类型包装起来
  • 拆箱:将包装器类型转换为基本类型

请看示例:

public class Main {
    public static void main(String[] args) {
            Integer a = 100;
            Integer b = 100;
            Integer c = 128;
            Integer d = 128;
            System.out.println(a==b);
            System.out.println(c==d);
    }
}

上面这段代码的输出结果:true false
很多人看到这个结果会很疑惑,为什么会是一个 true 一个 flase

其实从源码中可以很容易找到原因.
首先找到 Integer 方法中的 valueOf 方法

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

当不满足 if 语句中的条件,就会重新创建一个对象返回,那结果必然不相等。继续打开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() {}
      }

代码挺长,大概说的就是在通过 valueOf 方法创建 Integer 对象的时候,如果数值在[-128,127]
之间,便返回指向 IntegerCache.cache 中已经存在的对象的引用;否则创建一个新的 Integer
对象。所以上面代码中 a 与 b 相等, c 与 d 不相等。

在看下面的代码会输出什么

public class Main {
    public static void main(String[] args) {
            Double a = 1.0;
            Double b = 1.0;
            Double c = 2.0;
            Double d = 2.0;
            System.out.println(a==b);
            System.out.println(c==d);
    }
}

flase
flase
采用同样的方法,可以看到 Double 的 valueOf 方法,每次返回都是重新 new 一个新的对象,所以上面代码中的结果都不想等。

public static Double valueOf(double d) {
         return new Double(d);
}

最后再看这段代码的输出结果

public class Main {
    public static void main(String[] args) {
        Boolean a = false;
        Boolean b = false;
        Boolean c = true;
        Boolean d = true;
        System.out.println(a==b);
        System.out.println(c==d);
    }
}

true
true

继续看 valueOf 方法

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

再看看 TRUE 和 FALSE 是个什么东西,是两个静态成员属性。

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

结论 : Integer 、 Short 、 Byte 、 Character 、 Long 这几个类的 valueOf 方法的实现是类似
的。 Double 、 Float 的 valueOf 方法的实现是类似的。然后是 Boolean 的 valueOf 方法是单独一组的。
Integer i = new Integer(xxx) 和 Integer i =xxx 的区别
这两者的区别主要是第一种会触发自动装箱,第二者不会
最后看看下面这段程序的输出结果

public class Main {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Long g = 3L;
        int int1 = 12;
        int int2 = 12;
        Integer integer1 = new Integer(12);
        Integer integer2 = new Integer(12);
        Integer integer3 = new Integer(1);
        System.out.println("c==(a+b) ->"+ (c==(a+b)));
        System.out.println("g==(a+b) ->" + (g==(a+b)));
        System.out.println( "c.equals(a+b) ->" + (c.equals(a+b)));
        System.out.println( "g.equals(a+b) ->" + (g.equals(a+b)));
        System.out.println("int1 == int2 -> " + (int1 == int2));
        System.out.println("int1 == integer1 -> " + (int1 == integer1));
        System.out.println("integer1 == integer2 -> " + (integer1 == integer2));
        System.out.println("integer3 == a1 -> " + (integer3 == a));
    }
}

c==(a+b) ->true
g==(a+b) ->true
c.equals(a+b) ->true
g.equals(a+b) ->false
int1 == int2 -> true
int1 == integer1 -> true
integer1 == integer2 -> false
integer3 == a1 -> false

下面简单解释这些结果。
1.当== 运算符的两个操作数都是包装器类型的引用,则是比较指向的是否是同一个对象,而如果 其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。所 以 c==a+b , g==a+b 为 true 。

2.而对于 equals 方法会先触发自动拆箱过程,再触发自动装箱过程。也就是说a+b,会先各调 用 intValue 方法,得到了加法运算后的数值之后,便调用 Integer.valueOf 方法,再进行 equals 比较。所以 c.equals(a+b)为 true 。而对于 g.equals(a+b) , a+b 会先拆箱进行相加 运算,在装箱进行 equals 比较,但是装箱后为Integer , g 为 Long ,所以 g.equals(a+b) 为 false 。

  1. int1 == int2 为 true 无需解释, int1 == integer1 ,在进行比较时, integer1 会先进行 一个拆箱操作变成 int 型在进行比较,所以 int1 == integer1 为 true 。
  1. integer1 == integer2 -> false 。 integer1 和 integer2 都是通过 new 关键字创建的,可以 看成两个对象,所以 integer1 == integer2 为 false 。 integer3 == a1 ->false , integer3 是一个对象类型,而 a1 是一个常量它们存放内存的位置不一样,所以 integer3 == a1 为false ,具体原因可学习下java的内存模型。
  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byg_qlh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值