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