null 不好,我真的推荐你使用 Optional

2023-11-18 22:45:10 字數 6264 閱讀 3492

"null 很糟糕。" doug lea。

doug lea 是一位美国的计算机科学家,他是 j**a 平台的并发和集合框架的主要设计者之一。他在 2014 年的一篇文章中说过:“null sucks.”1,意思是 null 很糟糕。他认为 null 是一种不明确的表示,它既可以表示一个值不存在,也可以表示一个值未知,也可以表示一个值无效。这样就会导致很多逻辑错误和空指针异常,给程序员带来很多麻烦。他建议使用 optional 类来封装可能为空的值,从而提高**的可读性和健壮性。

"发明 null 引用是我的十亿美元错误。" sir c. a. r. hoare。

sir c. a. r. hoare 是一位英国的计算机科学家,他是快速排序算法、hoare 逻辑和通信顺序进程等重要概念的发明者。他在 2009 年的一个软件会议上道歉说:“i call it my billion-dollar mistake. it was the invention of the null reference in 1965.”,意思是他把 null 引用称为他的十亿美元错误。他说他在 1965 年设计 algol w 语言时,引入了 null 引用的概念,用来表示一个对象变量没有指向任何对象。他当时认为这是一个很简单和自然的想法,但后来发现这是一个非常糟糕的设计,因为它导致了无数的错误、漏洞和系统崩溃。他说他应该使用一个特殊的对象来表示空值,而不是使用 null。

自作者从事 j**a 编程一来,就与 null 引用相伴,与 nullpointerexception 相遇已经是家常便饭了。

null 引用是一种表示一个对象变量没有指向任何对象的方式,它是 j**a 语言中的一个特殊值,也是导致空指针异常(nullpointerexception)的主要原因。虽然 null 引用可以用来表示一个值不存在或未知,也可以用来节省内存空间。但是它也不符合面向对象的思想,因为它不是一个对象,不能调用任何方法或属性。

可以看到,null 引用并不好,我们应该尽量避免使用 null,那么我们该怎么避免 null 引用引起的逻辑错误和运行时异常嘞?

其实这个问题 j**a 的设计者也知道,于是他们在 j**a8 之后设计引入了 optional 类解决这个问题,本文将给大家详细介绍下 optional 类的设计目的以及使用方法。

optional 类是 j**a 8 中引入的一个新的类,它的作用是封装一个可能为空的值,从而避免空指针异常(nullpointerexception)。optional 类可以看作是一个容器,它可以包含一个非空的值,也可以为空。optional 类提供了一些方法,让我们可以更方便地处理可能为空的值,而不需要显式地进行空值检查或者使用 null。

optional 类的设计是基于函数式编程的思想,它借鉴了 scala 和 haskell 等语言中的 option 类型。optional 类实现了 j**a.util.function 包中的 supplier、consumer、predicate、function 等接口,这使得它可以和 lambda 表达式或者方法引用一起使用,形成更简洁和优雅的**。

optional 类被 final 修饰,因此它是一个不可变的类,它有两个静态方法用于创建 optional 对象。

optional.empty 表示一个空的 optional 对象,它不包含任何值。

// 创建一个空的 optional 对象optional empty = optional.empty();
optional.of 表示一个非空的 optional 对象,它包含一个非空的值。

// 创建一个非空的 optional 对象optional hello = optional.of("hello");
注意,如果我们使用 optional.of 方法传入一个 null 值,会抛出 nullpointerexception。如果我们不确定一个值是否为空,可以使用 optional.ofnullable 方法,它会根据值是否为空,返回一个相应的 optional 对象。例如:

// 创建一个可能为空的 optional 对象optional name = optional.ofnullable("hello");
optional 对象提供了一些方法,让我们可以更方便地处理可能为空的值,而不需要显式地进行空值检查或者使用 null。以下是一些常用的方法。

判断 optional 对象是否包含一个非空的值,返回一个布尔值。

如果 optional 对象包含一个非空的值,返回该值,否则抛出 nosuchelementexception 异常。

// 使用 ispresent 和 get 方法optional name = optional.ofnullable("tom");if (name.ispresent())else //输出:hello tom
如果 optional 对象包含一个非空的值,执行给定的消费者操作,否则什么也不做。

// 使用 ifpresent(consumer action)optional name = optional.ofnullable("tom");name.ifpresent(s ->输出:hello tom
如果 optional 对象包含一个非空的值,返回该值,否则返回给定的默认值。

// 使用 orelse(t other)optional name = optional.ofnullable(null);string greeting = hello, "name.orelse("guest");system.out.println(greeting);/输出:hello guest
如果 optional 对象包含一个非空的值,返回该值,否则返回由给定的**者操作生成的值。

// 使用 orelseget(supplier supplier)optional name = optional.ofnullable(null);string greeting = hello, "name.orelseget(()guset");system.out.println(greeting);/输出:hello guset
如果 optional 对象包含一个非空的值,返回该值,否则抛出由给定的异常**者操作生成的异常。

// 使用 orelsethrow(supplier exceptionsupplier)optional name = optional.ofnullable(null);string greeting = hello, "name.orelsethrow(()new nullpointerexception("null"))抛出 j**a.lang.nullpointerexception: null 异常
如果 optional 对象包含一个非空的值,对该值应用给定的映射函数,返回一个包含映射结果的 optional 对象,否则返回一个空的 optional 对象。

// 使用 map(function mapper)optional name = optional.ofnullable("tom");string greeting = hello, "name.map(s ->s.touppercase())get();system.out.println(greeting);/输出:hello tom
如果 optional 对象包含一个非空的值,对该值进行 mapper 参数操作,返回新的 optional 对象,否则返回一个空的 optional 对象。

// 使用 flatmap(function> mapper)optional name = optional.ofnullable("tom");string greeting = name.flatmap(s ->optional.of("hello " s)).get();system.out.println(greeting);/输出:hello tom
如果 optional 对象包含一个非空的值,并且该值满足给定的谓词条件,返回包含该值的 optional 对象,否则返回一个空的 optional 对象。

// filter(predicate predicate)optional name = optional.ofnullable("tom");string greeting = hello " name.filter(s ->s.isempty())get();system.out.println(greeting);/输出:hello tom
j**a 9 中 optional 类有了一些改进,主要是增加了三个新的方法,分别是 stream()、ifpresentorelse() 和 or()。这些方法可以让我们更方便地处理可能为空的值,以及和流或其他返回 optional 的方法结合使用。我来详细讲解一下这些方法的作用和用法。

这个方法可以将一个 optional 对象转换为一个 stream 对象,如果 optional 对象包含一个非空的值,那么返回的 stream 对象就包含这个值,否则返回一个空的 stream 对象。这样我们就可以利用 stream 的各种操作来处理 optional 的值,而不需要显式地判断是否为空。我们可以用 stream() 方法来过滤一个包含 optional 的列表,只保留非空的值,如下所示:

list> list = arrays.aslist( optional.empty(),optional.of("a"),optional.empty(),optional.of("b"))使用 stream() 方法过滤列表,只保留非空的值list filteredlist = list.stream() flatmap(optional::stream) .collect(collectors.tolist())system.out.println(filteredlist);/输出 [a, b]
这个方法可以让我们在 optional 对象包含值或者为空时,执行不同的操作。它接受两个参数,一个是 consumer 类型的 action,一个是 runnable 类型的 emptyaction。如果 optional 对象包含一个非空的值,那么就执行 action.accept(value),如果 optional 对象为空,那么就执行 emptyaction.run()。这样我们就可以避免使用 if-else 语句来判断 optional 是否为空,而是使用函数式编程的方式来处理不同的情况。我们可以用 ifpresentorelse() 方法来打印 optional 的值,或者提示不可用,如下所示 :

optional optional = optional.of(1);optional.ifpresentorelse( x ->system.out.println("value: "x), system.out.println("not present.")optional = optional.empty();optional.ifpresentorelse( x ->system.out.println("value: "x), system.out.println("not present.")输出:value: 1// 输出:not present.
这个方法可以让我们在 optional 对象为空时,返回一个预设的值。它接受一个 supplier 类型的 supplier,如果 optional 对象包含一个非空的值,那么就返回这个 optional 对象本身,如果 optional 对象为空,那么就返回 supplier.get() 返回的 optional 对象。这样我们就可以避免使用三元运算符或者其他方式来设置默认值,而是使用函数式编程的方式来提供备选值。我们可以用 or() 方法来设置 optional 的默认值,如下所示:

optional optional = optional.of("hello ")supplier> supplier = optional.of("tom");optional = optional.or(supplier);optional.ifpresent(x ->system.out.println(x));optional = optional.empty();optional = optional.or(supplier);optional.ifpresent(x ->system.out.println(x));输出:hello //输出:tom
最后我总结一下使用 optional 类的几个好处:

可以避免空指针异常,提高**的健壮性和可读性。

可以减少显式的空值检查和 null 的使用,使**更简洁和优雅。

可以利用函数式编程的特性,实现更灵活和高效的逻辑处理。

可以提高**的可测试性,方便进行单元测试和集成测试。

总之,optional 类是一个非常有用的类,它可以帮助我们更好地处理可能为空的值,提高**的质量和效率。所以我强烈推荐你在 j**a 开发中使用 optional 类,你会发现它的魅力和好处。

作者:waynblog

*:www.cnblogs.com/waynaqua/p/17840114.html

选择适合你的食用油 山茶油我推荐本草天香

食用油是我们日常饮食中必不可少的一部分。不同类型的食用油具有不同的特点和用途,因此选择适合自己的食用油非常重要。本文将介绍一些常见的食用油类型,并提供一些建议,帮助你在购买食用油时做出明智的选择。.橄榄油。橄榄油是一种非常健康的食用油,被广泛认可为地中海饮食的重要组成部分。它富含单不饱和脂肪酸,有助...

你可能真的不会用字帖!正确使用指南请收好

万卷君发现,不少书友字帖到手,不管三七二十一,翻开就开始蒙着写,描着写,按照自己的感觉随便写。写了一行 两行 三行,一页 两页 三页 结果发现,每个字还是一模一样的丑没有一个像字帖中的例字。停!你的字帖用错了!其实无论什么字帖,就算字体不同,但临帖的方法是大致相通的。今天万卷君以瘦金体 千字文 为例...

平价好用的面膜推荐!选面膜不想踩雷的就看这!

平价好用的 推荐!现在大部分女孩子可以不化妆,但是每天的护肤是必须的!不管肌肤状态再好,也是要认认真真的做好护肤工作!一张健康细腻的脸蛋子,是真的很让人羡慕,所以选择适合自己的 是非常重要的!适合自己的 可以从根源解决肌肤干燥缺水的问题,从而让肌肤状态变得更好更健康。目前市面上 品牌有很多,那我们该...