
image
空指針異常我想是程序員見到比較多的異常啦,今天來探索的這個(gè)Optional工具類就是來處理這類問題的。用過Google Guava(后期應(yīng)該會出一個(gè)系列,請持續(xù)關(guān)注)的都應(yīng)該知道,Guava這套工具類庫里面也有一個(gè)Optional,而且作用和今天來探索的這個(gè)java新特性是一樣的。既然又是探索,那我們先打開idea,然后ctrl+鼠標(biāo)左鍵進(jìn)到optional的世界看一下吧。
源碼片段
接下來我將逐行解釋一下源碼(像我這樣給jdk源碼這樣加注釋的怕是很少了_)
// final修飾說明此類是無法被引用的哈
public final class Optional<T> {
// 這個(gè)是EMPTY的實(shí)例
private static final Optional<?> EMPTY = new Optional<>();
// 如果非空,則為該值;如果為空,則表示不存在任何值。
private final T value;
// 構(gòu)造私有看來此類也不能被new
private Optional() {
this.value = null;
}
// 返回一個(gè)空的實(shí)例,@SuppressWarnings不提醒警告
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
// 根據(jù)value來構(gòu)造出一個(gè)實(shí)例
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// 返回一個(gè)帶有value的optional,注意value如果為空則會報(bào)空指針異常
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);
}
// 如果當(dāng)前有值則返回當(dāng)前值,否則拋出NoSuchElementException
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
// 如果這個(gè)Optional是存在的則返回true,否則為false
public boolean isPresent() {
return value != null;
}
// 如果option對象保存的值不是null,則調(diào)用consumer對象,否則不調(diào)用
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
// 判斷Optional對象中保存的值是否滿足Predicate,并返回新的Optional。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
// 如果value不為null,則進(jìn)行函數(shù)運(yùn)算,返回一個(gè)新的Optional,否則返回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));
}
}
// 上一章講到過Stream里面的flatMap,就是對一個(gè)大的集合進(jìn)行一個(gè)扁平化的操作。
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;
}
// 怎么辦?也不想解釋,關(guān)于Supplier供給者函數(shù)式的作用麻煩翻到此系列的第二章
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();
}
}
// 重寫了Object的方法
@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);
}
// 重寫了Object的方法
@Override
public int hashCode() {
return Objects.hashCode(value);
}
// 如果值不為空則返回Optional[value],否則Optional.empty。認(rèn)真看過我上一章的也許還能記憶起來
@Override
public String toString() {
return value != null
? String.format("Optional[%s]", value)
: "Optional.empty";
}
}
優(yōu)雅食用
這里撿幾個(gè)比較常用的在這里列出來吧
of && ofNullable
上面注釋有提到,這兩個(gè)都是被用來創(chuàng)建Optional對象。區(qū)別在于ofNullable還判空了。這就造成了ofNullable的實(shí)用性比of要高那么一丟丟。下面來看一個(gè)例子吧~
public class OptionalDemo {
public static void main(String[] args) {
Optional<String> ofNullable = Optional.ofNullable(null);
System.out.println(ofNullable);// Optional.empty
Optional<String> of = Optional.of(null); // 代碼執(zhí)行到這里會拋出NullPointerException
}
}
isPresent
isPresent有兩種作用:一個(gè)是判斷是否有值,還有一個(gè)返回的是void,如果不為空的話執(zhí)行Consumer消費(fèi)型函數(shù)式代碼。
public class OptionalDemo {
public static void main(String[] args) {
// 先創(chuàng)建一個(gè)Optional
Optional<String> val = Optional.ofNullable("yes");
System.out.println(val.isPresent()); // true
val.ifPresent(s -> System.out.println(s.concat(" or no?"))); // yes or no?
}
}
filter && map
直接看例子最好啦
public class OptionalDemo {
public static void main(String[] args) {
Optional<String> optional = Optional.ofNullable("code666");
Optional<String> newOptional = optional.map(param->param.concat(".top"));
System.out.println(newOptional); // Optional[code666.top]
Optional filterOptional = optional.filter(param->param.contentEquals("Sean")); // 如果條件成立的話會返回Optional[code666]
System.out.println(filterOptional); // Optional.empty
}
}
orElse && orElseGet
長得雖然差不多,orElseGet還帶了一個(gè)Supplier供給者函數(shù)看著高大上一點(diǎn),其實(shí)也差不多。記得在第二章有說過,供給者函數(shù)就有點(diǎn)像工廠的味道而已。
public class OptionalDemo {
public static void main(String[] args) {
String res = (String) Optional.ofNullable(null).orElse("這個(gè)結(jié)果為空");
System.out.println(res); // 這個(gè)結(jié)果為空
String res2 = (String) Optional.ofNullable(null).orElseGet(()-> "The result is empty.");
System.out.println(res2); // The result is empty.
}
}