学会使用Optional检查代码

本文介绍了Java 1.8中Optional类如何帮助开发者避免NullPointerException,通过实例演示Optional的用法及其优点,重点讲解了Optional.ofNullable和Optional.empty的区别。
摘要由CSDN通过智能技术生成

1、前言
作为一名Java程序员,无论是初入茅庐的菜鸟,还是久经江湖的高手,曾经肯定遭遇过各种各样的异常错误。在国外的一篇文章中,就统计了关于异常类型的排行榜,如下图:

是的,你没有看错,NullPointerException位居榜首。

Null Reference的发明者Charles Antony Richard Hoare说过:“我称之为我的十亿美元错误。这是1965年发明空引用的结果……这导致了无数的错误,漏洞和系统崩溃,在最近40年中可能造成十亿美元的痛苦和破坏。”

这看起来有些夸张,但毫无争议的是NullPointerException简直就是程序员心中的痛,并不是说它有多难以解决,而是为了解决它我们需要再付出了额外代价。

还记得当初刚入行时候的你,三天两头碰到NullPointerException而引发的bug,解决完一个,又在另一个地方遇到。这也慢慢让你懂得,不要相信任何“对象”,特别是别人提供给你的,在使用的地方都加上判断,这样就放心多了。于是代码通常就变成了下面这样:

String name = "Unknown";
if (null != people) {
    if (null != people.getName()) {
        name = people.getName();
    }
}
return name;

这样处理,虽然不用担心NullPointerException了,但是过多的判断语句着实让人头皮发麻,代码变得臃肿不堪。如果对象过于复杂,对象里面还有对象等等,你还要继续逐层判断么?

令人兴奋的是,JDK1.8引入了一个新类java.util.Optional<T>,凭借Optional类提供的API,我们再也不用担心NullPointerException了,更不会再去写那些烦人的判断啦。

2、Optional类
举例来说,使用新类意味着,如果你知道一个人可能有也可能没有车,那么Person类内部的car变量就不应该声明为Car,遭遇某人没有车时把null引用赋值给它,而是应该像下图这样直接将其声明为Optional类型。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tsaZpPjQ-1597913478274)(./7.Optional示例图.png)]

变量存在时,Optional类只是对类简单封装。变量不存在时,缺失的值会被建模成一个“空”的Optional对象,由方法Optional.empty()返回。Optional.empty()方法是一个静态工厂方法,它返回Optional类的特定单一实例。

Optional,本质上是一个容器对象,拥有一个非空值或空值,需要我们将对象实例传入该容器中。如果值存在,Optional.isPresent()方法返回true,并通过Optional.get()方法获取值。

Optional的构造方法为private,无法直接使用new来创建Optional对象,只能使用Optional提供的静态方法创建。

Optional提供的创建方法如下:

Optional.of(obj):如果对象为 null,将会抛出NullPointerException。
Optional.ofNullable(obj):如果对象为 null,将会创建不包含值的 EMPTY Optional对象实例(new Optional<>())。
Optional.empty() :等同于 Optional.ofNullable(null)。
其中,源码片段如下:

/**
 * Constructs an instance with the value present.
 *
 * @param value the non-null value to be present
 * @throws NullPointerException if value is null
 */
private Optional(T value) {
    this.value = Objects.requireNonNull(value);
}

……

/**
 * Returns an {@code Optional} with the specified present non-null value.
 *
 * @param <T> the class of the value
 * @param value the value to be present, which must be non-null
 * @return an {@code Optional} with the value present
 * @throws NullPointerException if value is null
 */
public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

/**
 * Returns an {@code Optional} describing the specified value, if non-null,
 * otherwise returns an empty {@code Optional}.
 *
 * @param <T> the class of the value
 * @param value the possibly-null value to describe
 * @return an {@code Optional} with a present value if the specified value
 * is non-null, otherwise an empty {@code Optional}
 */
public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}

/**
 * Common instance for {@code empty()}.
 */
private static final Optional<?> EMPTY = new Optional<>();

……

/**
 * Returns an empty {@code Optional} instance.  No value is present for this
 * Optional.
 *
 * @apiNote Though it may be tempting to do so, avoid testing if an object
 * is empty by comparing with {@code ==} against instances returned by
 * {@code Option.empty()}. There is no guarantee that it is a singleton.
 * Instead, use {@link #isPresent()}.
 *
 * @param <T> Type of the non-existent value
 * @return an empty {@code Optional}
 */
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

强烈建议使用Optional.ofNullable(obj)方法,来创建Optional对象,并获取对应值。

更多请见:http://www.mark-to-win.com/tutorial/50327.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值