作为开发人员每天与NullPointerException斗智斗勇。每接纳到参数或调用办法取得值得判别一下能否为null。稍不留意,空指针异常就像幽魂一样呈现了。
这篇文章我们来学习Java8是如何经过Optional类来防止空指针异常的。
先来看一下不运用Optional类时,我们为了避免NullPointerException会怎样处置。
为了避免呈现异常,需求不停的判别对象能否为null。但假如业务逻辑比拟复杂,会涌现出大量的ifelse。看似逻辑缜密,但易读性却并不高。
为理解决相关问题,在Effective Java中倡议若办法返回类型为汇合,则经过返回空汇合以防止 NullPointerException,真是煞费苦心。
先看一下上面的代码运用Optional之后会变成什么样子。
对照一下代码,看看神不神奇?!
Optional类简介
java.util.Optional类的引入很好的处理空指针异常,类声明如下:
public final class Optional{}
java.util.Optional类是一个封装了Optional值的容器对象,Optional值能够为null,假如值存在,调用isPresent()办法返回true,调用get()办法能够获取值。
经过源代码会发现,它并没有完成java.io.Serializable接口,因而应防止在类属性中运用,避免意想不到的问题。
除了Optional类之外,还扩展了一些常用类型的Optional对象,比方:OptionalDouble、OptionalInt、OptionalLong。用法根本上类似。
下面经过详细的操作和功用来理解Optional类。
创立Optional对象
创立Optional对象有三种办法:empty()、of()、ofNullable(),均为静态办法。
假如Optional对象没有值则用empty()办法。
Optional empty = Optional.empty();
假如肯定Optional对象的值不为null,则可用of()办法。
Optional stringOptional = Optional.of("Hello 公众号:程序新视界");
假如不肯定Optional对象的值能否为null,则可用ofNullable()。比方上面,不肯定Person对象是不否null,就用了ofNullable()办法。当然,也能够直接给该办法传null。
Optional ofNullOptional = Optional.ofNullable(null);
此时,经过调用其isPresent办法能够查看该Optional中能否值为null。
boolean bool = ofNullOptional.isPresent();System.out.println(bool);
此时假如直接调用get办法获取值,则会抛出异常。
ofNullOptional.get();
get获取Optional中的值
经过get办法可获取Optional中的值,但假如值为null,则会抛出异常。
Optional ofNullOptional = Optional.ofNullable(null);ofNullOptional.get();
异常信息:
java.util.NoSuchElementException: No value present at java.util.Optional.get(Optional.java:135)...
此时,需求另外一个办法的辅助:isPresent()。该办法可断定Optional中能否有值,假如有则返回true,假如没有则返回false。
map获取Optional中的值
关于对象操作,也能够经过map来获取值,最开端简化的例子就是如此。
map办法,假如有值,则对其执行调用映射函数得到返回值。假如返回值不为null,则创立包含映射返回值的Optional作为map办法返回值,否则返回空Optional。
flatMap获取Optional中的值
假如有值,则返回Optional类型返回值,否则返回空Optional。flatMap与map办法相似。但flatMap中的mapper返回值必需是Optional。调用完毕时,flatMap不会对结果用Optional封装。
OptionalsonOptional = Optional.ofNullable(son);sonOptional.flatMap(OptionalTest::getOptionalPerson);
调用的是当前类OptionalTest的另外一个办法:
orElse获取Optional中的值
orElse办法,假如有值就返回,否则返回一个给定的值作为默许值;
Optional.empty().orElse("--");复制代码
上面这种状况就会返回“--”。
在此,这种操作与三目运算效果一样。
str != null ? str : "--"复制代码
orElseGet获取Optional中的值
orElseGet()办法与orElse()办法作用相似,但生成默许值的方式不同。该办法承受一个Supplier函数式接口参数,用于生成默许值;
很显然,这里能够处置更多的业务逻辑。
orElseThrow获取Optional中的值
orElseThrow()办法与get()办法相似,当值为null时调用会抛出NullPointerException异常,但该办法能够指定抛出的异常类型。
Optional.empty().orElseThrow(()-> new RuntimeException("请先关注公众号!"));
此时打印异常信息为:
Optional.empty().orElseThrow(()-> new RuntimeException("请先关注公众号!"));
判别并执行操作
ifPresent办法,可对值停止判别然后打印,接纳参数为Consumer函数式接口。
Optional.of("公众号:程序新视界").ifPresent(System.out::println);
当然,也能够在函数中执行其他复杂操作:
filter()办法过滤
filter()办法可用于判别Optional对象能否满足给定条件,普通用于条件过滤:
运用误区
关于运用Optional的误区有以下:
正确的运用创立办法,不肯定能否为null时尽量选择ofNullable办法。
防止用在成员变量上(缘由上面曾经提到);
防止直接调用Optional对象的get和isPresent办法;
最后一条可能难了解,试想一下假如先用isPresent办法取得能否存在,然后决议能否调用get办法和之前的ifelse判别并无二致。
Java8倡导函数式编程,新增的许多API都能够用函数式编程表示,Optional类也是其中之一。