AutoBoxing与Unboxing细节分析(一)

首先,让大家看个简单的程序:

 

      public class AutoBoxingTester {
          public static void judgeEqual(Integer i, Integer j) {
              if (i == j) {
                  System.out.println("Equal!");
              } else {
                  System.out.println("Not Equal!");
              }
          }
       
          public static void main(String[] args) {
              Integer i = 100;
              Integer j = 100;
              judgeEqual(i, j);
              
              Integer a = 255;
              Integer b = 255;
              judgeEqual(a, b);
          }
       
      }


大家会觉得程序输出结果是什么呢?两个"Equal"?或者两个"Not Equal"?
 
可能程序的输出结果会与大家预期的想法有点出入,程序在第一次判断中会输出"Equal",而在第二次判断中会输出"Not Equal"。为什么会这样呢?这就要从Java 1.5加入的新特性,Autoboxing与Unboxing讲起了。
 
int、 short、char等,是Java中的Primitive类型,也就是非对象类型,因此,Java提供了一种Wrapper Class(包装类),像是Integer、Short、Character等,用来把Primitive类型的变量包装成对象类型。在Java 1.5之前的版本,这种转换需要通过手工进行,但是做这样的转换是编程过程中是很繁琐的,所以Java 1.5借由boxing消除了这种"不合理"的需求,JVM会自动处理从Primitive类型到对象Wrapper类型的转换,反之亦然。

上面的程序是两个Wrapper对象的比较,100和255分别被box进两个不同的对象i和j,a和b中,然后两个对象以"=="来作比较,因为两个对象 是不同的实例,有着不同的内存地址,所以按道理来说,程序两次判断的输出都应该为"Not Equal"才正确。然而,为什么程序第一次判断的输出会为"Equal"呢?难道是JVM出错了吗?

非也!Java规范指出:特定的Primitive一定得被box成相同的不可变的wrapper对象。这些对象会被高速缓存重复使用,并且会被当作一般的对象使用。这些特定的Primitive包括:boolean值的true和false、所有的byte值、介于-128至127的short与int的值、以及介于\u0000与\u007F之间的任何一个char。

所以,JVM确实对i和j使用了相同的对象实例(以及内存地址),因此,"=="运算符的结果为true,在第一次判断中自然就会输出Equal了。


在编程过程中必须小心注意此种情况的出现,因为它极可能会引发一些古怪而又难以发现的Bug。

你可能感兴趣的:(java,jvm,编程,J#)