Integer陷阱

概述

今天同事遇到一个关于 Integer 的坑:有两个 Integer 对象,Integer i = 10000,Integer j = 10000,判断两个对象是否相等。Java里面基本类型都有对应的对象,并且回进行自动装箱和拆箱的操作,就误以为对象 i 和对象 j 是比较的整形值,但是结果确出乎意料。

参考代码

public class Test {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;

        System.out.println(a == b);
        Integer i = 100001;
        Integer j = 100001;

        System.out.println(i == j);
    }
}

运行结果为:

true
false

本以为输出结果应该是两个true,但是最终的答案出乎意料,于是查看编译以后Test类对应的字节码命令,字节码命令如下:

javap -v Test.class

得到的字节码命令如下:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=5, args_size=1
         0: bipush        100
         2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: astore_1      
         6: bipush        100
         8: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        11: astore_2      
        12: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        15: aload_1       
        16: aload_2       
        17: if_acmpne     24
        20: iconst_1      
        21: goto          25
        24: iconst_0      
        25: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
        28: ldc           #5                  // int 100001
        30: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        33: astore_3      
        34: ldc           #5                  // int 100001
        36: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        39: astore        4
        41: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        44: aload_3       
        45: aload         4
        47: if_acmpne     54
        50: iconst_1      
        51: goto          55
        54: iconst_0      
        55: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V
        58: return        

通过上面的字节码命令可以看出,Integer 的装箱是通过 invokestatic 指令,调用 Integer.valueOf() 方法实现的。对两个对象进行比较时,是通过 if_acmpne 指令比较两个Integer对象,接下来我们看看 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);
    }

IntegerCache.low = -128, IntegerCache.high = 127,在Integer中将 -128 到 127 对应的 Integer 对象缓存到 IntegerCache中,如果给 Integer对象赋值 >= -128 或者 赋值 <= 127,就从缓存中获取,如果超出了 -128 - 127的范围,就在堆中创建一个 Integer 对象,感兴趣的同学可以用 HSDB 工具查看。

if_acmpne 指令会进行两个对象的比较,如果内存地址不一样就返回 false,这就解释了上面的情况,所以比较两个对象的时候还是调用equals方法靠谱

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 12,254评论 6 13
  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,882评论 0 11
  • 以下内容为作者辛苦原创,版权归作者所有,如转载演绎请在“光变”微信公众号留言申请,转载文章请在开始处显著标明出处。...
    光变阅读 1,791评论 3 6
  • 我还是很喜欢你 ,像风走了八千里 ,不见归期。 我还是很喜欢你 ,像春来秋去 ,从无停息 。 我还是很喜欢你 ,像...
    kingZhou520阅读 431评论 0 1
  • 去年的现在我们正好考完搭乘车回到了自己的学校。后来大家一起吃了一顿饭,各种调侃和祝福和开心,此时的我们还不知道毕...
    我想我想SXM阅读 221评论 0 1

友情链接更多精彩内容