"用 Optional 作为返回类型能避免 NPE"是常见说法。真实写一个返回 Optional<String> 却直接 return null 的方法,看看这句话在语言机制层面到底成不成立。
上一篇:thenApply 真实可能在调用线程执行,不一定是线程池:真实测出两种结果
先确认 Optional 本身设计上没问题的那一部分:空值调用 get() 会真实、明确地抛出异常,不是静默返回 null。
empty.get() 真实抛出 NoSuchElementException: No value present
这一点符合设计初衷:相比直接返回 null 然后在某个遥远的地方莫名其妙 NPE,Optional.get() 在明确没有值的时候会真实、立刻、带着清晰信息地失败。
Optional 只是一个普通的类,Java 语言没有任何机制阻止一个声明为 Optional<T> 的引用真实指向 null。
OptionalDemo.java(一个真实存在于不少代码库里的坏例子) static Optional<String> badMethod(boolean giveNull) { if (giveNull) { return null; // 编译器完全不会阻止这一行 } return Optional.of("真实值"); }
badMethod(true) 返回的 Optional 本身是不是 null = true 对返回值调用 isPresent() 真实抛出 NullPointerException——Optional 类型完全没能阻止这一点
真实结果确认了这一点:badMethod(true) 声明的返回类型是 Optional<String>,方法体里真实写了 return null;,javac 真实没有报任何错误或警告——这行代码完全合法。调用方如果天真地相信"返回类型是 Optional 就不用判空了",直接调用 isPresent(),真实立刻踩到 NullPointerException,而且这个异常和"忘了判断 Optional 内部有没有值"是两件完全不同的事——问题出在更早的一层,Optional 这个容器本身都没拿到。
当方法真实、规范地返回了一个 Optional 实例(不是 null)时,orElse/ifPresentOrElse 这类方法能让调用方完全不用写 if 判断。
goodResult.orElse("默认值") = 默认值
真实走了 ifPresentOrElse 的空分支,没有抛异常
Optional.of(null) 真实立刻抛出 NullPointerException Optional.ofNullable(null) 真实不抛异常,isPresent() = false
每一行都是真实运行这段代码得到的结果或真实抛出的异常。