Null 的含糊语义让人很不舒服。Null 不多能够明确地表示某种语义,例如,Map.get(key)返回 Null时,可能表示 map 中的值是 null,亦或 map 中没有 key 对应的值。Null 能够表示失败、成功或几乎任何状况。使用 Null 之外的特定值,会让你的逻辑描述变得更清晰。java
Null 确实也有合适和正确的使用场景,如在性能和速度方面 Null 是廉价的,并且在对象数组中,出现 Null 也是没法避免的。但相对于底层库来讲,在应用级别的代码中,Null 每每是致使混乱,疑难问题和模糊语义的元凶,就如同咱们举过的 Map.get(key)的例子。最关键的是,Null 自己没有定义它表达的意思。数组
从官方文档中能够总结出为何有时候要避免使用null的缘由:工具
null能够表示空指针、空对象、甚至初始化为null,从人的思惟角度上去想,确实能明白null在各场景的意义,可是对于计算机而言null是多种意义,难以区分的。就如上述例子“Map.get(key)返回 Null时,可能表示 map 中的值是 null,亦或 map 中没有 key 对应的值”。性能
鉴于这些缘由,不少 Guava 工具类对 Null 值都采用快速失败操做,除非工具类自己提供了针对 Null 值的因变措施。此外,Guava 还提供了不少工具类,让你更方便地用特定值替换 Null 值。google
考虑一下使用天然的 null 对象——特殊值。举例来讲,为某个 enum 类型增长特殊的枚举值表示 null,好比 java.math.RoundingMode 就定义了一个枚举值 UNNECESSARY,它表示一种不作任何舍入操做的模式,用这种模式作舍入操做会直接抛出异常。 若是你真的须要使用 null 值,可是 null 值不能和 Guava 中的集合实现一块儿工做,你只能选择其余实现。.net
使用null的方法:将意义混淆的null用一个表明null的参数代替。指针
大多数状况下,开发人员使用 null 代表的是某种缺失情形:多是已经有一个默认值,或没有值,或找不到值。例如,Map.get 返回 null 就表示找不到给定键对应的值。 Guava 用 Optional表示可能为 null 的 T 类型引用。一个 Optional 实例可能包含非 null 的引用(咱们称之为引用存在),也可能什么也不包括(称之为引用缺失)。它从不说包含的是 null 值,而是用存在或缺失来表示。但Optional 从不会包含 null 值引用。code
java.util.Optional是java8的新特性。orm
其实从以上3点能够看出,不管是对null判断返回true和false仍是解决空指针异常问题,其实都是减小 null 判断以及 NullPointerException 的异常发生,尽可能减小直接对null的判断。对象
Optional<Integer> possible = Optional.of(5); possible.isPresent(); // returns true possible.get(); // returns 5
方法类型 | 方法名 | 描述 |
---|---|---|
static <T> Optional<T> | Optional.of(T reference) | 若引用为null则快速失败 抛出异常java.lang.NullPointerException |
static <T> Optional<T> | Optional.absent() | 建立引用缺失的Optional实例 |
static <T> Optional<T> | Optional.fromNullable(T nullableReference) | 若是 nullableReference 非null,返回包含该引用的Optional实例,不然返回 absent(). |
static <T> @Nullable Optional<T> | Optional.fromJavaUtil(java.util.Optional<T>) | 返回给定的java.util.Optional,等效com.google.common.base.Optional值,若是参数为null,则返回null |
static <T> Iterable<T> | Optional.presentInstances(Iterable<? extends Optional<? extends T>> optionals) | 从提供的选项中返回每一个当前实例的值,按顺序跳过absent()的出现次数 |
static <T> Optional<T> | Optional.toJavaUtil(com.google.common.base.Optional<T>) | 返回给定com.google.common.base.Optional的等效java.util.Optional值,若是参数为null,则返回null |
方法类型 | 方法名 | 描述 | 备注 |
---|---|---|---|
abstract Set<T> | asSet() | 返回一个不可变的单集的惟一元素所包含的实例(若是存在),不然为一个空的不可变的集合 | asSet返回的是一个不可变的set集合,若是对这个set集合作增删改的操做会抛异常 |
abstract boolean | equals(@Nullable Object object) | 返回boolean,object是一个Optional实例,而且所包含的引用彼此相等或都不存在 | 与常见得Object的equals是一样用法 |
abstract T | get() | 返回所包含的实例,该实例必须存在 | 返回包含在Optional内实例 |
abstract int | hashCode() | 返回此实例的哈希码 | 返回此实例的哈希码 |
abstract boolean | isPresent() | 返回true此持有者是否包含(非空)实例。 | Optional内的实例存在返回true,不然false |
abstract Optional<T> | or(Optional<? extends T> secondChoice) | Optional若是存在值,则返回此值;secondChoice除此之外 | 若是Optional中有实例则返回实例,不然返回secondChoice |
abstract T | or(Supplier<? extends T> supplier) | 返回包含的实例(若是存在);supplier.get()除此之外 | 若是Optional中有实例则返回实例,不然返回supplier.get() |
abstract T | or(T defaultValue) | 返回包含的实例(若是存在);defaultValue除此之外 | 若是Optional中有实例则返回实例,不然返回defaultValue |
abstract T | orNull() | 返回包含的实例(若是存在);null除此之外 | 若是Optional中有实例则返回实例,不然返回null |
static <T> Iterable<T> | toJavaUtil() | 返回与java.util.Optional此可选值的等效值 | 其实是调用了java.util.Optional.ofNullable,返回Optional<T> |
abstract <V> Optional<V> | transform(Function<? super T,V> function) | 若是实例存在,则使用给定的实例进行转换Function;不然, absent()返回 | 判断function是否为null,是则返回null,不是调用toJavaUtil() |
import com.google.common.base.Optional; public class GuavaTest { public static void main(String args[]) { GuavaTest demo = new GuavaTest(); Integer value1 = null; Integer value2 = new Integer(10); // Optional.fromNullable:容许参数为null. Optional<Integer> a = Optional.fromNullable(value1); // Optional.of:若是参数为null,则抛出NullPointerException Optional<Integer> b = Optional.of(value2); System.out.println(demo.sum(a, b)); } public Integer sum(Optional<Integer> a, Optional<Integer> b) { // Optional.isPresent:检查值是否存在 System.out.println("第一个参数是否存在: " + a.isPresent()); System.out.println("第二个参数是否存在: " + b.isPresent()); // Optional.or:若是存在则返回值,不然返回传递的默认值 Integer value1 = a.or(new Integer(0)); // Optional.get:获取值,此时有值存在 Integer value2 = b.get(); return value1 + value2; } }
根据2.2.2的实例方法的描述和备注,2.2.3的例子不难看出整个Optional都是为了服务于null的处理,例如设置一个默认值,Optional是作一个数据保护的做用,在可能出现空指针的地方对数据的一个数据处理,主要是对null的处理。