Java8-Optional

Java8-Optional

Optional是一個class,可以包含也可以不包含非null值。Optional在Java 8中導入。
目的是為了解决NullPointerExceptions的問題。
A container object which may or may not contain a non-null value.
If a value is present, {@code isPresent()} will return {@code true} and
{@code get()} will return the value.

before Optional

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
在Java 8之前,開發人員在方法內return null而不是Optional。這種方法有一些缺點。
第一是没有明確的方法來表示null可能是一個特殊值。相比之下,在API中返回Optional是明確的定義,
其中可能没有值。如果我们要確保不會出現NullPointerExceptions,則需要對每個引用進行檢查。

private void getIsoCode(User user){
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
}

Optional:staticOptionalempty()

1
2
3
4
// Creating an empty optional
Optional<String> empty = Optional.empty();
-----
Returns an empty {@code Optional} instance. No value is present for this Optional.

Optional:staticOptionalof(T value)

1
2
3
4
5
// Creating an optional using of
String name = "java";
Optional<String> opt = Optional.of(name);
-----
Returns an {@code Optional} with the specified present non-null value.

Optional:staticOptionalofNullable(T value)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Possible null value

Optional<String> optional = Optional.ofNullable(name());

private String name() {

String name = "Java";

return (name.length() > 5) ? name : null;

}
-----
Returns an {@code Optional} describing the specified value, if non-null,
otherwise returns an empty {@code Optional}.

Optional:boolean isPresent()

1
2
3
4
5
6
7
8
9
10
11
//ispresent

Optional optional1 = Optional.of("javaone");

if (optional1.isPresent()) {

//Do something, normally a get

}
-----
Return {@code true} if there is a value present, otherwise {@code false}.

Optional:void ifPresent(Consumer<? super T> consumer)

1
2
3
4
5
6
7
8
//ifpresent

Optional<String> optional1 = Optional.of("javaone");

optional1.ifPresent(s -> System.out.println(s.length()));
-----
If a value is present, invoke the specified consumer with the value,
otherwise do nothing.

Optional:T get()

1
2
3
4
5
6
7
8
//get
Optional<String> optional1 = Optional.of("javaone");
if (optional1.isPresent()){
String value = optional1.get();
}
-----
If a value is present in this {@code Optional}, returns the value,
otherwise throws {@code NoSuchElementException}.

Optional:T orElse(T other)

1
2
3
4
5
//orElse
String nullName = null;
String name = Optional.ofNullable(nullName).orElse("default_name");
-----
Return the value if present, otherwise return {@code other}.

Optional:T orElseGet(Supplier<? extends T> other)

1
2
3
4
5
//orElseGet
String name = Optional.ofNullable(nullName).orElseGet(() -> "david");
-----
Return the value if present, otherwise invoke {@code other} and return
the result of that invocation.

結論

1
2
3
4
5
6
When to use?
User user = users.stream().findFirst().orElse(new User("default", "1234"));
When don't use?
1.不可序列化
2.不能拿來做建構子或方法的參數,會導致代碼變複雜
User user = new User("[email protected]", "1234", Optional.empty());