基于版本: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. MySQL增强半同步几个重要参数搭配的测试

      Preface       Semi-synchronous replication is supported since MySQL 5.5 and then enhanced graduall ...

  2. heat launch an instance

    在包含Orchestration服务的环境中,可以创建启动实例的堆栈 创建yam文件 heat_template_version: 2015-10-15 description: Launch a b ...

  3. 最干净的pyinstaller打包成exe应用程序方法

    在anaconda环境下进行pyinstaller打包后,程序非常大,70行代码打包后有280MB,这是因为会将conda环境携带的库都打包进去导致的.为了获得更纯净的包环境,我们需要安装纯pytho ...

  4. 2 25urllib.py

    """ urllib.request.urlopen(url,data,timeout) """ # from urllib.request ...

  5. ocrosoft Contest1316 - 信奥编程之路~~~~~第三关 问题 x: 十进制到二进制的转换

    http://acm.ocrosoft.com/problem.php?cid=1316&pid=49 题目描述 把十进制到二进制的转换. 输入 234 输出 11101010 样例输入 23 ...

  6. 使用pl/sql在oracle中新建表和对应序列

    1.登录后再Table节点右键新建表: 开始编辑表结构 列 键约束 检查约束 查看sql,没问题的话点击应用,创建表 2.创建序列sequence,在Sequence节点右键新建 填写内容 查看sql ...

  7. [xsy1129] flow [树链剖分和线段树一起优化网络流][我也不知道这是什么鬼标签]

    题面 内部OJ 思路 考虑一个决策方案${x}$,$x_i$表示第$i$个点选不选,$f^k_i$表示点$i$的第$k$个父亲 那么可以得到总花费的表达式$ans=\sum V_i x_i - \su ...

  8. [codeforces] 526D [51nod] 1554 欧姆诺姆和项链

    原题 KMP 方法一: 听说是ex-kmp--来自学姐 ex-kmp是处理两个串s和t之间,t的每一个后缀在s中的最长前缀的长度的一个算法. 它很像manacher(至少我和学姐这么认为),记录了一个 ...

  9. Hash表模板

    namespace Hash { ; ; struct adj { ll nxt,v,num,val; }e[N]; ll head[H],ecnt=; void init() { ecnt=; me ...

  10. 洛谷 P2485 [SDOI2011]计算器 解题报告

    P2485 [SDOI2011]计算器 题目描述 你被要求设计一个计算器完成以下三项任务: 1.给定y.z.p,计算y^z mod p 的值: 2.给定y.z.p,计算满足xy ≡z(mod p)的最 ...