包装类==比较关于null 的问题

今天线上遇到一个空指针问题,觉得是一个小知识点,想想还是记录下来(拆箱问题)

  public static void main(String[] args) {
        int i=0;
        Integer s=null;
        if(s==i){
            System.out.println(s+"1");
        }else
        {
            System.out.println(s+"2");
        }

    }

写一个小demo,正常我们一个判断是上面这个代码块

上述integer和int 进行==比较,这样写的话会出现空指针

下面我们简化下来看下反编译之后的汇编指令.

  public static void main(String[] args) {
        int i=0;
        Integer s=null;
        boolean b=s==i;
    }

反编译结果如下:

 

 

 可以看到一个指令:invokevirtual -->调用实例方法,基于类进行分派,意思就是去调用integer的intValue方法

这样我们就可以知道为什么会出现空指针了(拆箱)

上面我们可以知道不同类型变量之前的比较会进行装箱拆箱,那相同类型是怎么比较的呢?

我们把上述代码进行小小的改变(i换成了integer)

  public static void main(String[] args) {
        Integer i=0;
        Integer s=null;
        boolean b=s==i;
    }

然后我们再看下反编译的代码

 

 

 首先iconst_0 -->,int取值0~5时JVM采用iconst_0、iconst_1、iconst_2、iconst_3、iconst_4、iconst_5指令将常量压入栈中,取值-1时采用iconst_m1指令将常量压入栈中

第二步调用integer的valueOf方法

 

这段代码我们应该很熟悉,integer的一个缓存方案,(-128~128),这里也涉及到一个integer的比较问题(最好使用equals比较,如果使用==的话要考虑128之后的问题)

 第三步astore_1-->要执行astore_1指令,JVM从操作数栈顶部弹出一个引用类型或者returnAddress类型值,然后将该值存入由索引1指定的局部变量中,即将引用类型或者returnAddress类型值存入局部变量1。

第四步aload_1-->从局部变量表的相应位置装载一个对象引用到操作数栈的栈顶

第五步:if_acmpne-->比较栈顶两引用类型数值,当结果不相等时跳转

经过两步aload 将值装载到操作数栈的栈顶,然后用if_acmpne进行比较

 

posted @ 2020-10-28 16:12  xwx唐宋元明清  阅读(162)  评论(0编辑  收藏  举报