深入剖析 Java 新特性
范学雷
前 Oracle 首席软件工程师,Java SE 安全组成员,OpenJDK 评审成员
16539 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 23 讲
深入剖析 Java 新特性
15
15
1.0x
00:00/00:00
登录|注册

14 | 禁止空指针,该怎么避免崩溃的空指针?

你好,我是范学雷。今天,我们讨论 Java 的空指针。
我们都知道空指针,它的发明者开玩笑似的,称它是一个价值 10 亿美元的错误;同时呢,他还称 C 语言的 get 方法是一个价值 100 亿美元的错误。空指针真的错得这么厉害吗?get 方法又有什么问题?我们能够在 Java 语言里改进或者消除空指针吗?
我们从阅读案例开始,来看一看该怎么理解这些问题,以及怎么降低这些问题的影响。

阅读案例

通常地,一个人的姓名包括两个部分,姓(Last Name)和名(First Name)。在有些文化里,也会使用中间名(Middle Name)。所以,我们通常可以使用姓、名、中间名这三个要素来标识一个人的姓名。用代码的形式表示出来,就是下面的代码这样。
public record FullName(String firstName,
String middleName, String lastName) {
// blank
}
中间名并不是必需的,因为有的人使用中间名,有的人不使用。现在我们假设,需要判断一个人的中间名是不是黛安(Diane)。这个判断的逻辑,可能就像下面的代码这样。
private static boolean hasMiddleName(
FullName fullName, String middleName) {
return fullName.middleName().equals(middleName);
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java中空指针异常一直是程序员们头疼的问题,本文通过案例分析了空指针异常的危害,并介绍了在JDK 17中对空指针异常信息的改进。文章强调了避免产生空指针异常的重要性,提出了使用空字符串替代空指针的方法,并讨论了Optional工具类在降低空指针风险方面的尝试。同时,文章也指出了Optional类带来的不必要复杂性和未能解决空指针问题的局限性。另外,文章还探讨了使用封闭类和模式匹配来强制执行空指针检查的新特性,以及这种设计所带来的影响和妥协。总的来说,本文提出了避免空指针异常的重要性,并介绍了一些在实际编程中可以采取的方法,对读者快速了解文章概览有很好的帮助。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入剖析 Java 新特性》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(15)

  • 最新
  • 精选
  • fatme
    1. 感觉 Optional 更有用的是 orElse, ifPresent, filter, map, flatMap 这些方法。isPresent 本质上和判断空指针的方式是一样的,没有优势 2. 像 Optional 是对 nullable 数据的支持,java 也可以增加对 required 数据的支持。比如增加 Required<T>, 编译器禁止对 Required 数据赋值 null。我们的代码变为:public record FullName(Required<String> firstName, String middleName, Required<String> lastName)。这样对哪些数据是可空,哪些数据是不可空,一目了然。 3. Retruned 的使用太复杂。我更愿意使用以下代码: switch (fullName.middleName()) { case null -> {...}; case String s -> {...}; }

    作者回复: 一门编程语言的最大目标,是程序员不犯错误,而不是好的程序员少犯错误。所以,在不同的角度看,答案也许不一样。 1. 除了isPresent,其他的方法都是附带的红利。 2. 如果能够消除空指针的产生,也就用不着Required了;如果消除不了,Required也不用着。 3. 这本质上和直接判断空指针是一样的,需要程序员的认真和代码阅读者的认真。如果都能够认真起来,就不存在空指针的问题了。 无论是GoLang还是Optional, Returned,和直接检查空指针相比,都没有简化代码。这是消除空指针影响的代价。

    2021-12-19
    1
  • 墨名次
    Returned跟Optional还是有些复杂, 在C#跟Kotlin里面我觉得挺简洁的,如果借鉴C#可以这样写: private static boolean hasMiddleName(FullName fullName, String middleName) { return fullName.middleName?.equals(middleName); } 就只加一个问号,如果需要判断fullName对象是否空那就前面再加一个问号

    作者回复: 这个写法有意思。非空的话,该怎么处理?

    2021-12-17
    3
    1
  • aoe
    开始使用 Optional 的时候确实也遇到了像文中说的空指针(以为使用后就能神奇的消除空指针),后来还错用了 Optional.of() 又遇到空指针,直到最后才发现 Optional.ofNullable() 才是能最大限度避免空指针的方法。 如果有需要返回 null 的地方,可以通过一个中间层封装其状态,避免直接返回 null; 或者今后 JDK 升级功能后像 Go 一样没有空指针异常了,但是 Go 的 panic 一样能让程序崩溃; 支持老师的观点:在我们的代码里,尽量不要产生空指针。没有空指针,也就没有了空指针的烦恼

    作者回复: Optional一言难尽啊

    2021-12-17
    2
    1
  • Jagger Chen
    老师您好,尝试将判断为 null 这段逻辑注释掉,编译器没有报错,是否说明没有完全地做到强制检查呢?谢谢 public Returned<String> middleName() { // if (middleName == null) { // return Returned.UNDEFINED; // } return new Returned.ReturnValue<>(middleName); }

    作者回复: 是的,这个if语句编译器不能强制性的检查。

    2021-12-21
  • 第二少
    Optional 在这样一种情景下特别有用: a.b.c.d.e.f 其中a,b,c,d,e,f都有可能为null,现在要访问f,进行一些处理,可以这么做: Optional.ofNullable(a).map(A::getB).map(B::getC).map(C::getD).map(D::getE).map(E::getF).ifPresent(f -> ...); 只要a,b,c,d,e,f中任何一个为null,后续的代码就不会继续执行,也不会抛出NPE

    作者回复: 用对了就好,不过容易用错,不是我喜欢的方式

    2021-12-17
    3
  • Calvin
    老师,这些课程最后的习题,能不能讲一下答案? 不然都不知道自己做的对不对,比如可以加餐一讲专门讲,这样也可以丰富一下这个课程的目录和内容。

    作者回复: 可以看看GitHub里同学们做的作业啊。如果GitHub的PR不能提供答案,我再看看怎么讲这些习题。

    2021-12-17
  • bigben
    用Returned并不比Optional有优势,代码比较冗长,整个公司统一比较难。java语言级为啥不提供更简单的方式呢?其它语言有可借鉴的好的方法吗?

    作者回复: 还在探索更简单的方式。

    2021-12-17
  • kimoti
    感觉那个Optional就是个鸡肋,你不还是得调一下isPresent方法吗?这和判断一下是否为NULL不是一样吗?
    2021-12-17
    2
    1
  • ifelse
    学习打卡
    2022-10-13归属地:浙江
  • shen
    上面消除null的其实就是空对象模式
    2022-05-03
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部