基于版本:Guava 22.0

Wiki:Using and avoiding null

0:Optional简介

null在很多场景下会引发问题,NullPointerException困扰过无数的程序员,Guava用快速失败的思路来显式的解决null问题

ps:JDK1.8也提供了Optional工具包

1. 类图

2. 设计思路

抽象类Optional有两个子类Absent与Present,Optional本身不保存对象,这两个子类才是对象的容器

Absent表示值为null的情况

Present表示值不为null的情况

如果对Absent调用get方法,则会直接抛出IllegalStateException异常

用这样的手段,Optional显式的解决了null问题

3. 构造方法

Optional与它的两个子类的构造器都是私有的,只能通过Optional的几个方法来构造对象

Optional.absent()
public static <T> Optional<T> absent() {
return Absent.withType();
} Absent.withType()
static final Absent<Object> INSTANCE = new Absent<Object>(); @SuppressWarnings("unchecked") // implementation is "fully variant"
static <T> Optional<T> withType() {
return (Optional<T>) INSTANCE;
}

可以很清楚的看出,Optional.absent方法只是返回Absent内置的一个标记对象罢了

Optional.of()
public static <T> Optional<T> of(T reference) {
return new Present<T>(checkNotNull(reference));
} Optional.checkNotNull
@CanIgnoreReturnValue
public static <T> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
}
return reference;
} Present()
private final T reference; Present(T reference) {
this.reference = reference;
}

Optional.of方法会先对传入的参数进行校验,null会引发异常,不为null的话才会用Present进行包装

  public static <T> Optional<T> fromNullable(@Nullable T nullableReference) {
return (nullableReference == null)
? Optional.<T>absent()
: new Present<T>(nullableReference);
}

Optional.fromNullable方法,如果传入值是null,会返回Absent,否则返回包装后的Present对象

4. get方法

Optional.get()
public abstract T get(); Absent.get()
@Override
public T get() {
throw new IllegalStateException("Optional.get() cannot be called on an absent value");
}

Present.get()

@Override
public T get() {
return reference;
}

Optional的get方法是抽象的,具体实现在子类中完成

Absent.get方法会直接抛出异常

Present.get方法会返回内部保存的值

由此实现了在value为null时,调用get方法会快速失败的语义

5. or方法

Optional.or()
public abstract T or(T defaultValue); Absent.or()
@Override
public T or(T defaultValue) {
return checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
} Present.or()
@Override
public T or(T defaultValue) {
checkNotNull(defaultValue, "use Optional.orNull() instead of Optional.or(null)");
return reference;
}

跟get方法相同的套路,相当于一个在value为null的时候返回默认值的get方法

6.orNull方法

Optional.orNull()
@Nullable
public abstract T orNull(); Absent.orNull()
@Override
@Nullable
public T orNull() {
return null;
} Present.orNull()
@Override
public T orNull() {
return reference;
}

同上,相当于一个在value为null时就返回null的get方法

7. 总结

Optional是一个很简单但又很实用的工具类,其设计模式是很值得我们学习的

Guava源码学习(一)Optional的更多相关文章

  1. Guava源码学习(五)EventBus

    基于版本:Guava 22.0 Wiki:EventBus 0. EventBus简介 提供了发布-订阅模型,可以方便的在EventBus上注册订阅者,发布者可以简单的将事件传递给EventBus,E ...

  2. Guava源码学习(二)Ordering

    基于版本:Guava 22.0 Wiki:Ordering 0. Ordering简介 Guava的Ordering提供了链式风格的比较器的实现,我们可以用Ordering轻松构建复杂的比较器. 1. ...

  3. Guava源码学习(零)前言

    Guava是由Google出品的Java类库,功能强大且易用. 后续我会用多篇博客介绍Guava的使用方法,以及从源码层面分析其实现原理. 分析次序基于Guava的官方Wiki 基于版本:Guava ...

  4. Guava源码学习(三)ImmutableCollection

    基于版本:Guava 22.0 Wiki:Immutable collections 0. ImmutableCollection简介 类似于JDK的Collections.unmodifiableX ...

  5. Guava源码学习(四)新集合类型

    基于版本:Guava 22.0 Wiki:New collection types 0. 简介 Guava提供了很多好用的集合工具,比如Multiset和BiMap,本文介绍了这些新集合类型的使用方式 ...

  6. caffe源码学习之Proto数据格式【1】

    前言: 由于业务需要,接触caffe已经有接近半年,一直忙着阅读各种论文,重现大大小小的模型. 期间也总结过一些caffe源码学习笔记,断断续续,这次打算系统的记录一下caffe源码学习笔记,巩固一下 ...

  7. Aspects 源码学习

    AOP 面向切面编程,在对于埋点.日志记录等操作来说是一个很好的解决方案.而 Aspects 是一个对于AOP编程的一个优雅的实现,也可以直接借助这个库来使用AOP思想.需要值得注意的是,Aspect ...

  8. Guava 源码分析(Cache 原理 对象引用、事件回调)

    前言 在上文「Guava 源码分析(Cache 原理)」中分析了 Guava Cache 的相关原理. 文末提到了回收机制.移除时间通知等内容,许多朋友也挺感兴趣,这次就这两个内容再来分析分析. 在开 ...

  9. mongo源码学习(三)请求接收传输层

    在上一篇博客中(mongo源码学习(二)db.cpp之mongoDbMain方法分析),我们把db.cpp中的mongoDbMain的执行过程分析了一下,最后会调用initAndListen(serv ...

随机推荐

  1. laravel5.5路由使用name的好处

    使用name的好处 辅助函数 route 可以用于为指定路由生成 URL.命名路由生成的 URL 不与路由上定义的 URL 相耦合.因此,就算路由的 URL 有任何更改,都不需要对 route 函数调 ...

  2. iOS 中 AFNetworking HTTPS 的使用

    由于我们公司由HTTP转HTTPS,出现了一系列问题特此记录下. 一.HTTPS 二.App Transport Security 三.iOS 中用HTTPS 注意的问题 四.使用 AFNetwork ...

  3. QA面试题:之一(中英文题目、难度:简单)

    QA面试题:之一(中英文题目.难度:简单)

  4. 容器基础(二): 使用Namespace进行边界隔离

    Linux Namespace 容器技术可以认为是一种沙盒(sandbox), 为了实现沙盒/容器/应用间的隔离,就需要一种技术来对容器界定边界,从而让容器不至于互相干扰.当前使用的技术就是Names ...

  5. Linux开启MySQL远程连接

    Linux开启MySQL远程连接的设置步骤 . MySQL默认root用户只能本地访问,不能远程连接管理MySQL数据库,那么Linux下如何开启MySQL远程连接?设置步骤如下: 1.GRANT命令 ...

  6. shell之ip命令

    转:出处我也不知道了,学习时候记下的笔记 1.作用 ip是iproute2软件包里面的一个强大的网络配置工具,它能够替代一些传统的网络管理工具,例如ifconfig.route等,使用权限为超级用户. ...

  7. HDU 4417 Super Mario ( 离线树状数组 )

    把数值和查询放在一起从小到大排序,纪录每个数值的位置,当遇到数值时就更新到树状数组中,遇到查询就直接查询该区间和. #include <cstdio> #include <cstri ...

  8. URAL 1732. Ministry of Truth ( KMP 多模式串匹配 )

    问在第一个串中删掉几个字符能否得到第二个串.注意在第二个串中不连续的单词在第一个串中也必须不连续. 一组数据: Input: abababbbbababbb aba ab Output: I HAVE ...

  9. ZOJ 3606 Lazy Salesgirl ( 线段树 + 思路 )

    卖切糕的小女孩 http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474672.html #include <cstdio> #inclu ...

  10. HDU 5790 Prefix(字典树+主席树)

    Prefix Time Limit: 2000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Sub ...