Guava-Optional使用

前言

Java开发中,null就像给黑洞,给错误的排查带来极大的难度,而Guavanull进行了优化,可以方便我们更优雅的处理null

Optional

Guava中使用Optional来处理null,如使用Optional(null)时,则会快速报错,而使用Java原生方式处理时,则会在具体使用到null时报错,下面通过一个示例说明。

示例

原生Java示例


package com.hust.grid.leesf.optional;

import com.google.common.base.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        Integer invalidInput = null;
        Integer validInput = 10;

        sum(invalidInput, validInput);
    }

    public static int sum(Integer i1, Integer i2) {
        return i1 + i2;
    }
}

运行结果如下:

Exception in thread “main” java.lang.NullPointerException
at com.hust.grid.leesf.optional.OptionalTest.sum(OptionalTest.java:18)
at com.hust.grid.leesf.optional.OptionalTest.main(OptionalTest.java:10)

可以看到,其会在sum方法中报错,即当运行i1 + i2时报错,若不采取合适的判断非null方法,则该程序会报错。

Guava示例


public class OptionalTest {
    public static void main(String[] args) {
        Integer invalidInput = null;
        Integer validInput = 10;

        Optional<Integer> i1 = Optional.of(invalidInput);
        Optional<Integer> i2 = Optional.of(validInput);

        sum(i1, i2);
        //sum1(invalidInput, validInput);
    }

    public static int sum(Optional<Integer> i1, Optional<Integer> i2) {
        return i1.get() + i2.get();
    }

运行结果如下:

Exception in thread “main” java.lang.NullPointerException
at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.common.base.Optional.of(Optional.java:86)
at com.hust.grid.leesf.optional.OptionalTest.main(OptionalTest.java:10)

可以看到在运行Optional.of(invalidInput)时报错了,不会调用sum方法,使用Optional来规避方法调用时的非null判断,使得能够更快速的抛出异常。

源码分析

创建非null对象

根据Guava示例,来简单分析Optional的源码,其有AbsentPresent两个子类,Absent代表nullPresent则代表非null,当调用Optional.of方法时,其会创建Present对象。

  • Optional.of方法首先调用checkNotNull(reference)方法。当referencenull时,则直接抛出NullPointerException异常,否则创建Present对象。
  • Present对象中有T reference的变量用于保存非null值。

创建null对象

除了创建非null对象外,还可以特意创建null对象,而创建null对象有两种方法,一种通过fromNullable方法,另一种通过absent方法。

fromNullable方法

可以通过Optional.fromNullable(null)方法创建,其会创建一个Absent对象表示null,而当调用Optional.fromNullable方法并且传递的参数不为null时,其会正常创建Present对象。

absent方法

直接通过调用Optional.absent方法即可创建一个Absent对象表示null

值得注意的是,所有的null对象都为同一个对象(哈希码相同)。

获取元素

上述方法可以通过Optional来保存传递的变量,再使用时,可调用Optionalget或者or方法获取值。

get方法

对于Absent对象而言,调用get会抛出异常;对于Present对象而言,调用get会返回reference变量。

or方法

对于Absent对象而言,调用or会返回传入的参数;对于Present对象而言,调用or会返回原本传入的变量值。

总结

Optional源码比较简单,主要是为了避免运行时null进行的优化。