1. 程式人生 > 實用技巧 >Optional類學習總結

Optional類學習總結

簡單瞭解Optional類


眾所周知,在日常開發中Null Pointer Exception 空指標異常是非常令人頭疼的一件事情,為了避免這個問題我們不得不在程式碼中穿插大量的判空程式碼使得程式碼看起來非常的不優雅.而Java1.8的新特性Optional類就是用來解決這個痛點的,下面就來簡單的瞭解一下Optional的使用吧.

   常規判斷:
        //物件 人
        //屬性有 name,age
        Person person=new Person();
       if (null==person){
            return "person為null";
        }
        return person;

     使用Optional:
        //物件 人
        //屬性有 name,age
        Person person=new Person();
        return Optional.ofNullable(person).orElse("person為null");

測試展示類Person程式碼

public class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

Option類的使用


Optional物件建立

首先我們先開啟Optional的原始碼把Optional物件的方法提取出來分析一下

public final class Optional<T> {
   private static final Optional<?> EMPTY = new Optional<>();
   private final T value;
   //我們可以看到兩個構造方格都是private 私有的
   //說明 我們沒辦法在外面去new出來Optional物件
   private Optional() {
        this.value = null;
    }
   private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }
    //這個靜態方法大致 是創建出一個包裝值為空的一個物件因為沒有任何引數賦值
   public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
    //這個靜態方法大致 是創建出一個包裝值非空的一個物件 因為做了賦值
   public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    //這個靜態方法大致是 如果引數value為空,則建立空物件,如果不為空,則建立有參物件
   public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
 }

例項呼叫一下看看

// 1、建立一個包裝物件值為空的Optional物件
Optional<String> optEmpty = Optional.empty();
// 2、建立包裝物件值非空的Optional物件
Optional<String> optOf = Optional.of("optional");
// 3、建立包裝物件值允許為空也可以不為空的Optional物件
Optional<String> optOfNullable1 = Optional.ofNullable(null);
Optional<String> optOfNullable2 = Optional.ofNullable("optional");

Optional.get()方法(返回物件的值)

原始碼如下:

//如果value不為空則做返回,如果為空則丟擲異常 "No value present" 
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

例項呼叫:

    public static void main(String[] args) {
        String hello = null;
        String world = Optional.ofNullable(hello).get();
    }
    //執行結果
    Exception in thread "main" java.util.NoSuchElementException: No value present
	at java.base/java.util.Optional.get(Optional.java:141)
	at Demo.main(Person.java:33)

Optional.isPresent()方法(判讀是否為空)

原始碼:

// isPresent()方法就是會返回一個boolean型別值,如果物件不為空則為真,如果為空則false
 public boolean isPresent() {
        return value != null;
    }

例項呼叫:

    public static void main(String[] args) {
        String hello= null;
        if (Optional.ofNullable(hello).isPresent()){
            //寫不為空的邏輯
            System.out.println("不為空");
        }else{
            //寫為空的邏輯
            System.out.println("為空");
        }
    }
    //執行結果
    為空

Optional.ifPresent()方法(判讀是否為空並返回函式)

原始碼:

//這個意思是如果物件非空,則執行函式體
public void ifPresent(Consumer<? super T> consumer) {
    //如果value不為空,則執行accept方法體
    if (value != null)
        consumer.accept(value);
}

例項呼叫:

public static void main(String[] args) {
    String hello = "world";
    Optional.ofNullable(hello).ifPresent(p -> System.out.println(hello));
}
//執行結果
world

Optional.filter()方法(過濾物件)

原始碼

// filter()方法大致意思是,接受一個物件,然後對他進行條件過濾,如果條件符合則返回Optional物件本身,如果不符合則返回空Optional 
public Optional<T> filter(Predicate<? super T> predicate) {
    Objects.requireNonNull(predicate);
    //如果為空直接返回this
    if (!isPresent())
        return this;
    else
    //判斷返回本身還是空Optional
        return predicate.test(value) ? this : empty();
}

例項:

public static void main(String[] args) {
    String hello = "world";
    Optional<String> a = Optional.ofNullable(hello).filter(p -> "world".equals(p));
    Optional<String> b = Optional.ofNullable(hello).filter(p -> "hello world".equals(p));
    System.out.println("a:" + a);
    System.out.println("b:" + b);
}
//執行結果
a:Optional[world]
b:Optional.empty

Optional.map()方法(物件進行二次包裝)

原始碼:

// map()方法將對應Funcation函式式介面中的物件,進行二次運算,封裝成新的物件然後返回在Optional中
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    //如果為空返回自己
    if (!isPresent())
        return empty();
    else {
    //否則返回用方法修飾過的Optional
        return Optional.ofNullable(mapper.apply(value));
    }
}

例項呼叫:

public static void main(String[] args) {
    String hello = null;
    String world = "world";
    String a = Optional.ofNullable(hello).map(p -> hello).orElse("hello為空");
    String b = Optional.ofNullable(world).map(p -> world).orElse("world為空");
    System.out.println("a:" + a);
    System.out.println("b:" + b);
}
//執行結果
a:hello為空
b:world

Optional.flatMap()方法(Optional物件進行二次包裝)

原始碼:

// 同map(),但是flatMap()不會自動封裝Optional,需要自行手動封裝
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Objects.requireNonNull(mapper.apply(value));
    }
}

例項呼叫:

public static void main(String[] args) {
    Person person = new Person();
    person.setSex("男");
    String aDefault = Optional.ofNullable(person).flatMap(p -> Optional.ofNullable(p.getSex())).orElse("default");
}

Optional.orElse()方法(為空返回物件)

原始碼:

// 這個方法意思是如果包裝物件為空的話,就執行orElse方法裡的value,如果非空,則返回寫入物件
public T orElse(T other) {
    //如果非空,返回value,如果為空,返回other
    return value != null ? value : other;
}

例項呼叫:

public static void main(String[] args) {
    Person person=new Person();
    person.setSex("男");
    Optional.ofNullable(person).orElse(new Person("女"));
}

Optional.orElseGet()方法(為空返回Supplier物件)

原始碼:

// 這個與orElse很相似,入參不一樣,入參為Supplier物件,為空返回傳入物件的.get()方法,如果非空則返回當前物件
public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

例項呼叫:

public static void main(String[] args) {
    Person person = new Person();
    Optional<Supplier<Person>> sup = Optional.ofNullable(Person::new);
    //呼叫get()方法,此時才會呼叫物件的構造方法,即獲得到真正物件
    Person person1 = Optional.ofNullable(person).orElseGet(sup.get());
}

Optional.orElseThrow()方法(為空返回異常)

原始碼:

// 如果為空,就丟擲你定義的異常,如果不為空返回當前物件
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

例項呼叫:

public static void main(String[] args) throws Exception {
    Person person = null;
    try {
            Optional.ofNullable(person).orElseThrow(() -> new
                Exception("null"));
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

jdk1.9對Optional優化

首先增加了三個方法: or()、ifPresentOrElse() 和 stream()。 or() 與orElse等方法相似,如果物件不為空返回物件,如果為空則返回or()方法中預設的值。ifPresentOrElse() 方法有兩個引數:一個 Consumer 和一個 Runnable。如果物件不為空,會執行 Consumer 的動作,否則執行 Runnable。相比ifPresent()多了OrElse判斷。stream()將Optional轉換成stream,如果有值就返回包含值的stream,如果沒值,就返回空的stream。