美文网首页
空指针异常-日常分析

空指针异常-日常分析

作者: Yellowtail | 来源:发表于2021-08-25 11:43 被阅读0次

概述

组内有同学问了一个问题,对于下面的代码,如果有空指针异常发生,那么可能出现在什么地方

favoriteHouseInfo.setKeyStatus(Null.ofInt(teamHouse::getKeyStatus));

语法分析

MommyTalk-222.png

LaTex链接

代码执行顺序为

step1: 得到方法引用

teamHouse::getKeyStatus 是一个方法引用,意思是得到一个对象的方法引用(粗略理解为方法指针),便于在后面的代码里执行
这一步执行完成之后,代码变为了

favoriteHouseInfo.setKeyStatus(Null.ofInt(() -> *ptr method));

由上面的逻辑可知,如果一个对象是null,是没有方法的,所以这里可能会产生空指针异常

step2:工具类执行lambda表达式

Null.ofInt 是一个工具类,代码如下

public static final <T> T ofInt(Supplier<T> expr) {
        Supplier<T> defaultValues = () -> (T) new Integer(0);
        return of(expr, defaultValues);
}

public static final <T> T of(Supplier<T> expr, Supplier<T> defaultValue) {
        try {
            T result = expr.get();

            if (result == null) {
                return defaultValue.get();
            }
            return result;
        } catch (NullPointerException | IndexOutOfBoundsException e) {
            return defaultValue.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

可以看到会去执行 expr.get()
expr 其实就是 () -> *ptr method), 可以理解为无入参代码块
如果有空指针异常,会被捕获

step3: 拆箱

(为什么3在前,4在后,一会儿分析)
对于步骤2的Integer返回值对象,执行 intValue方法
可能有空指针

step4: 得到方法签名

步骤3的结果,作为入参,执行 favoriteHouseInfo 对象的 setKeyStatus 方法
方法(除了静态)一定是和对象联系起来的,无对象,无方法, 所以有可能有空指针异常

结论

方法引用 ,背后逻辑是需要获取一个对象的方法引用, 可能有空指针
自动拆箱,背后逻辑是默认执行xxValue()方法,null对象是没有方法的,可能有空指针
方法执行,null对象是没有方法的,可能有空指针

思考

到底是先拆箱再执行方法,还是先得到方法签名,再拆箱,再执行呢

对于以下代码

public class NullTest {

    @Test
    public void testProject() {

        Hello hello = null;

        hello.setInt(
                getValue());

    }

    Integer getValue() {
        return null;
    }

    class Hello {

        void setInt(int a) {

        }
    }
}

编译之后再反编译

javap -verbose NullTest.class

看一下内容


image.png

可以看到在编译期间就已经决定了执行顺序

  1. 执行getValue()
  2. 拆箱,执行 intValue()
  3. 执行 setInt()

相关文章

网友评论

      本文标题:空指针异常-日常分析

      本文链接:https://www.haomeiwen.com/subject/wvusiltx.html