表面上看来这只是一些基础的问题
当真正的了解了以后你就会发现
啊
原来是这么一回事!下文是几道Java谜题
不仔细分析就会犯错哦
等于还是不等于?
看来看下面的一段代码
代码片段
public static void main(final String[] args) { Integer a = new Integer(); Integer b = ; Systemoutprintln(a == b); }
这段代码的输出是什么?相信很多人都会很容易的猜到false因为ab两个对象的地址不同用==比较时是false恭喜你答对了
再看下面的一段代码
代码片段
public static void main(final String[] args) { Integer a = ; Integer b = ; Systemoutprintln(a == b); }
你可能会回答这没什么不一样啊所以还是false很遗憾如果你执行上面的一段代码结果是true
上面的代码可能让你有些意外那好吧再看看下面的这段代码
代码片段
public static void main(final String[] args) { Integer a = ; Integer b = ; Systemoutprintln(a == b); }
结果是true吗?很遗憾如果你执行上面的一段代码结果是false
感到吃惊吗?那最后再看下面的一段代码
代码片段
public static void main(final String[] args) { Integer a = IntegervalueOf(); Integer b = ; Systemoutprintln(a == b); }
最后的结果可能你已经猜到了是true
为什么会这样?
现在我们分析一下上面的代码可以很容易的看出这一系列代码的最终目的都是用==对两个对象进行比较Java中如果用==比较两个对象结果为true说明这两个对象实际上是同一个对象false说明是两个对象
现在我们来看看为什么会出现上面的现象
我们先看代码片段最后的运行结果是true说明ab两个对象实际上是同一个对象但是a对象是通过调用Integer的valueOf方法创建的而b对象是通过自动装箱创建出来的怎么会是同一个对象呢?难道问题在字节码那里毕竟Java程序是依靠虚拟器运行字节码来实现的
通过jdk中自带的工具javap解析字节码核心的部分摘取如下
: bipush : invokestatic #; //Method java/lang/IntegervalueOf:(I)Ljava/lang/Integer; : astore_ : bipush : invokestatic #; //Method java/lang/IntegervalueOf:(I)Ljava/lang/Integer;
代码中我们只调用了一次IntegervalueOf方法但是字节码中出现了两次对IntegervalueOf方法的调用那么另一次是哪里呢?只可能在自动装箱时调用的因此这段代码实际上等价于
public static void main(final String[] args) { Integer a = IntegervalueOf(); Integer b = IntegervalueOf(); Systemoutprintln(a == b); }
现在问题就简单了看jdk源代码查看valueOf方法的具体实现
public static Integer valueOf(int i) { final int offset = ; if (i >= && i <= ) { // must cache return IntegerCachecache[i + offset]; } return new Integer(i); }
看到这儿上面的代码就很明确了对于到的数字valueOf返回的是缓存中的对象所以两次调用IntegervalueOf()返回的都是同一个对象
我们再先看代码片段根据上面的分析代码片段实际上等价于以下代码
public static void main(final String[] args) { Integer a = IntegervalueOf(); Integer b = IntegervalueOf(); Systemoutprintln(a == b); }
由于不在到范围内所以两个对象都是通过new Integer()的方式创建的所以最后结果为false
片段和片段就不做具体分析了相信读者可以自行分析
最后请大家思考一下问题通过上面的分析了解到整数的自动装箱是通过IntegervalueOf(int number)实现的那么自动拆箱是如何实现的呢?