java8 Optional靜態類簡介,以及用法

在java8中,很多的stream的終端操作,都返回了一個Optional<T>對象,這個對象,是用來解決空指針的問題,而產生的一個類;我們先看下,這個類的一些定義

import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
 
public final class Optional<T> {
    private static final Optional<?> EMPTY = new Optional<>();
 
    private final T value;
 
    private Optional() {
        this.value = null;
    }
 
    public static <T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
 
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }
 
    public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
 
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
 
    public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
 
    public boolean isPresent() {
        return value != null;
    }
 
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
 
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }
 
    public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
 
    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 T orElse(T other) {
        return value != null ? value : other;
    }
 
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }
 
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
 
        if (!(obj instanceof Optional)) {
            return false;
        }
 
        Optional<?> other = (Optional<?>) obj;
        return Objects.equals(value, other.value);
    }
 
    @Override
    public int hashCode() {
        return Objects.hashCode(value);
    }
 
    @Override
    public String toString() {
        return value != null ? String.format("Optional[%s]", value) : "Optional.empty";
    }
}

上面這些定義,我把java的源代碼,去掉了註釋,所展示的部分,我們可以看下,這個類,有兩個構造方法,以及三個靜態方法

如下

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);
    }
 
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);

構造方法被私有化,外部不能直接創建這個對象,靜態方法中,也提供了實例化這個類的三個靜態方法,

第一個是empty方法,直接返回一個類加載後就創建的一個空的optional對象,

第二個是of(T value)方法,可以看到,直接new了一個optional對象;

第三個是ofNullable(T value)方法,可以看到,這個方法,先對傳入的泛型對象,做了null的判斷,爲null的話,返回第一個靜態方法的空對象;

創建完optional對象後,我們來看下,取到這個泛型對象的幾個方法

public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
 
    public T orElse(T other) {
        return value != null ? value : other;
    }
 
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }
 
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

可以看到,有4種取泛型參數的方式;

1.get()直接取,如果爲null,就返回異常

2.orElse(T other)在取這個對象的時候,設置一個默認對象(默認值);如果當前對象爲null的時候,就返回默認對象

3.orElseGet(Supplier<? extends T> other)跟第二個是一樣的,區別只是參數,傳入了一個函數式參數;

4. orElseThrow(Supplier<? extends X> exceptionSupplier)第四個,跟上面表達的是一樣的,爲null的時候,返回一個特定的異常;

下面,我們再看下,剩下的幾個方法

public boolean isPresent() {
        return value != null;
    }
 
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
 
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
    }
 
    public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
 
    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));
        }
    }

isPresent()是對當前的value進行null判斷

ifPresent(Consumer<? super T> consumer)具體的意思,可以參看《JAVA8 Consumer接口》,理解了consumer接口,也就理解了這個方法;

filter(Predicate<? super T> predicate),map(Function<? super T, ? extends U> mapper) ,flatMap(Function<? super T, Optional<U>> mapper) 這幾個方法的應用,可以參看我的《JAVA8 Stream接口,map操作,filter操作,flatMap操作》,跟stream的上的方法,用法是一致的,沒有區別;

最後,我們用幾個案例,來演示一下,這個類的使用方式,大家自己觀看代碼,就不做解釋了

import java.util.Arrays;
 
public class Test {
 
    public static void main(String[] args) {
        Arrays.asList("a", "b", "c");
        Emp emp = new Emp("xiaoMing", "上海", "11");
        Optional<Emp> op = Optional.ofNullable(emp);
        System.out.println(op.get().getAddress());// 上海
        Optional<Emp> op1 = Optional.ofNullable(null);
        System.out.println(op1.orElse(emp).getAddress());// 上海
        /*
         * 這裏指定了一個默認對象emp,爲先創建的一個emp對象,emp對象裏的成員變量還沒有複製,所以輸出爲null
         */
        System.out.println(op1.orElseGet(Emp::new).getAddress());
        try {
            System.out.println(op1.orElseThrow(RuntimeException::new));// java.lang.RuntimeException
 
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(op1.get().getAddress());// java.util.NoSuchElementException
        } catch (Exception e) {
            e.printStackTrace();
        }
        String address = op.filter(obj -> obj.getAddress().equals("上海")).map(str -> str.getAddress()).get();
        System.out.println(address);// 上海
 
    }
 
    static class Emp {
        private String name;
 
        private String address;
 
        private String age;
 
        public Emp() {
            super();
        }
 
        public Emp(String name, String address, String age) {
            super();
            this.name = name;
            this.address = address;
            this.age = age;
        }
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
 
        public String getAddress() {
            return address;
        }
 
        public void setAddress(String address) {
            this.address = address;
        }
 
        public String getAge() {
            return age;
        }
 
        public void setAge(String age) {
            this.age = age;
        }
 
    }
}


 

1.lambda表達式
《java8 Lambda表達式簡介》

《java8 lambda表達式,方法的引用以及構造器的引用》

2.函數式接口
《java8 函數式接口簡介》

《JAVA8 Function接口以及同類型的特化的接口》

《JAVA8 Consumer接口》

《JAVA8 Supplier接口》

《JAVA8 UnaryOperator接口》

《JAVA8 BiConsumer 接口》

3.stream接口操作

《java8 Stream接口簡介》

《 java8 Stream-創建流的幾種方式》

《JAVA8 stream接口 中間操作和終端操作》

《JAVA8 Stream接口,map操作,filter操作,flatMap操作》

《JAVA8 stream接口 distinct,sorted,peek,limit,skip》

《java8 stream接口 終端操作 forEachOrdered和forEach》

《java8 stream接口 終端操作 toArray操作》

《java8 stream接口 終端操作 min,max,findFirst,findAny操作》

《java8 stream接口終端操作 count,anyMatch,allMatch,noneMatch》

《java8 srteam接口終端操作reduce操作》

《java8 stream接口 終端操作 collect操作》

4.其他部分

《java8 Optional靜態類簡介,以及用法》

發佈了13 篇原創文章 · 獲贊 12 · 訪問量 4543
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章