Table of Contents
ToggleInitialize Optional in Java
初始化 Optional 容器內有兩種狀態,有值或無值,系統開發時,經常會出現 NullPointerException 的例外,如果沒有經過特別處理,很容易造成系統崩潰,使用 Optional 可以指定要返回的替代值或要運行的替代程式碼,讓程式碼更具可讀性, Initialize Optional Java 介紹常見的 empty 、 of 、 ofNullable 等方法,初始化 Optional 容器物件,本篇增加了範例,並透過單元測試來驗證產出結果。
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- optional
| +- InitializeOptionalTest.java
單元測試
Java Initialize Optional 提供初始化 Optional 。
empty
Java Initialize Optional 建立空的 Optional 容器。
@Test
public void empty() {
Optional<String> emptyOpt = Optional.empty();
System.out.println(emptyOpt);
assertFalse(emptyOpt.isPresent());
System.out.println(emptyOpt);
emptyOpt = Optional.ofNullable(null);
assertFalse(emptyOpt.isPresent());
Optional.empty
Optional.empty
of
Java Initialize Optional 建立 Optional 容器,內有字串、整數、物件及集合等不同類型物件。
@NoArgsConstructor
@Getter
@Setter
@Builder
public static class Food {
private String name;
private double quantity;
private int type;
public Food(String name, double quantity, int type) {
this.name = name;
this.quantity = quantity;
this.type = type;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
builder.appendSuper(super.toString());
builder.append("name", name);
builder.append("quantity", quantity);
builder.append("type", type);
return builder.toString();
}
public boolean equals(Object object) {
if (!(object instanceof Food)) {
return false;
}
if (this == object) {
return true;
}
Food other = (Food) object;
return new EqualsBuilder().append(getName(), other.getName()).isEquals();
}
public int hashCode() {
return new HashCodeBuilder().append(getName()).toHashCode();
}
}
@Test
public void of() {
Optional<String> opt = Optional.of("Beef");
System.out.println(opt);
assertTrue(opt.isPresent());
System.out.println(opt.get());
Optional<Integer> intOpt = Optional.of(147);
System.out.println(intOpt);
assertTrue(intOpt.isPresent());
System.out.println(intOpt.get());
Food food = new Food("Chicken", 2, 1);
Optional<Food> foodOpt = Optional.of(food);
System.out.println(foodOpt);
assertTrue(foodOpt.isPresent());
System.out.println(foodOpt.get());
List<Food> list = new ArrayList<>();
list.add(food);
list.add(new Food("Duck", 3, 1));
Optional<List<Food>> listOpt = Optional.of(list);
System.out.println(listOpt);
assertTrue(listOpt.isPresent());
System.out.println(listOpt.get());
}
Optional[Beef]
Beef
Optional[147]
147
Optional[{"name":"Chicken","quantity":2.0,"type":1}]
{"name":"Chicken","quantity":2.0,"type":1}
Optional[[{"name":"Chicken","quantity":2.0,"type":1}, {"name":"Duck","quantity":3.0,"type":1}]]
[{"name":"Chicken","quantity":2.0,"type":1}, {"name":"Duck","quantity":3.0,"type":1}]
ofThrowException
Java Initialize Optional 建立 Optional 容器,傳入參數 null ,會拋出例外 。
@Test(expected = NullPointerException.class)
public void ofThrowException() {
Optional<String> opt = Optional.of(null);
assertFalse(opt.isPresent());
}
java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at org.ruoxue.java_147.optional.InitializeOptionalTest.ofThrowException(InitializeOptionalTest.java:102)
ofNullable
Java Initialize Optional 建立 Optional 容器,內有字串、整數、物件及集合等不同類型物件。
@Test
public void ofNullable() {
Optional<String> opt = Optional.ofNullable("Beef");
System.out.println(opt);
assertTrue(opt.isPresent());
System.out.println(opt.get());
Optional<Integer> intOpt = Optional.ofNullable(147);
System.out.println(intOpt);
assertTrue(intOpt.isPresent());
System.out.println(intOpt.get());
Food food = new Food("Chicken", 2, 1);
Optional<Food> foodOpt = Optional.ofNullable(food);
System.out.println(foodOpt);
assertTrue(foodOpt.isPresent());
System.out.println(foodOpt.get());
List<Food> list = new ArrayList<>();
list.add(food);
list.add(new Food("Duck", 3, 1));
Optional<List<Food>> listOpt = Optional.ofNullable(list);
System.out.println(listOpt);
assertTrue(listOpt.isPresent());
System.out.println(listOpt.get());
}
Optional[Beef]
Beef
Optional[147]
147
Optional[{"name":"Chicken","quantity":2.0,"type":1}]
{"name":"Chicken","quantity":2.0,"type":1}
Optional[[{"name":"Chicken","quantity":2.0,"type":1}, {"name":"Duck","quantity":3.0,"type":1}]]
[{"name":"Chicken","quantity":2.0,"type":1}, {"name":"Duck","quantity":3.0,"type":1}]
ofNullableWithNull
Optional Initialization Java 建立 Optional 容器,可傳入參數 null 。
@Test
public void ofNullableWithNull() {
Optional<String> opt = Optional.ofNullable(null);
System.out.println(opt);
assertFalse(opt.isPresent());
System.out.println(opt.orElse("DEFAULT_VALUE"));
Optional<Integer> intOpt = Optional.ofNullable(null);
System.out.println(intOpt);
assertFalse(intOpt.isPresent());
System.out.println(intOpt.orElse(0));
Optional<Food> foodOpt = Optional.ofNullable(null);
System.out.println(foodOpt);
assertFalse(foodOpt.isPresent());
System.out.println(foodOpt.orElse(null));
Optional<List<Food>> listOpt = Optional.ofNullable(null);
System.out.println(listOpt);
assertFalse(listOpt.isPresent());
System.out.println(listOpt.orElseGet(() -> new ArrayList<Food>()));
}
Optional.empty
DEFAULT_VALUE
Optional.empty
0
Optional.empty
null
Optional.empty
[]
getListWithTraditional
Optional Initialization Java 建立 FoodList 物件, list 初值為 null ,使用傳統方式延遲建構建立 List。
public static class FoodList {
List<Food> list = null;
public List<Food> getListWithTraditional() {
if (null == this.list) {
this.list = new ArrayList<Food>();
}
return this.list;
}
public List<Food> getListWithOptional() {
return Optional.ofNullable(this.list).orElseGet(ArrayList::new);
}
}
@Test
public void getListWithTraditional() {
FoodList foodList = new FoodList();
List<Food> list = foodList.getListWithTraditional();
System.out.println(list);
assertNotNull(list);
}
[]
getListWithOptional
Optional Initialization Java 建立 FoodList 物件, list 初值為 null ,使用 Optional 方式延遲建構建立 List。
@Test
public void getListWithOptional() {
FoodList foodList = new FoodList();
List<Food> list = foodList.getListWithOptional();
System.out.println(list);
assertNotNull(list);
}
[]
InitializeOptionalTest.java
Optional Initialization Java 新增單元測試,驗證是否符合預期。
package org.ruoxue.java_147.optional;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Test;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
public class InitializeOptionalTest {
@Test
public void empty() {
Optional<String> emptyOpt = Optional.empty();
System.out.println(emptyOpt);
assertFalse(emptyOpt.isPresent());
System.out.println(emptyOpt);
emptyOpt = Optional.ofNullable(null);
assertFalse(emptyOpt.isPresent());
}
@NoArgsConstructor
@Getter
@Setter
@Builder
public static class Food {
private String name;
private double quantity;
private int type;
public Food(String name, double quantity, int type) {
this.name = name;
this.quantity = quantity;
this.type = type;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
builder.appendSuper(super.toString());
builder.append("name", name);
builder.append("quantity", quantity);
builder.append("type", type);
return builder.toString();
}
public boolean equals(Object object) {
if (!(object instanceof Food)) {
return false;
}
if (this == object) {
return true;
}
Food other = (Food) object;
return new EqualsBuilder().append(getName(), other.getName()).isEquals();
}
public int hashCode() {
return new HashCodeBuilder().append(getName()).toHashCode();
}
}
@Test
public void of() {
Optional<String> opt = Optional.of("Beef");
System.out.println(opt);
assertTrue(opt.isPresent());
System.out.println(opt.get());
Optional<Integer> intOpt = Optional.of(147);
System.out.println(intOpt);
assertTrue(intOpt.isPresent());
System.out.println(intOpt.get());
Food food = new Food("Chicken", 2, 1);
Optional<Food> foodOpt = Optional.of(food);
System.out.println(foodOpt);
assertTrue(foodOpt.isPresent());
System.out.println(foodOpt.get());
List<Food> list = new ArrayList<>();
list.add(food);
list.add(new Food("Duck", 3, 1));
Optional<List<Food>> listOpt = Optional.of(list);
System.out.println(listOpt);
assertTrue(listOpt.isPresent());
System.out.println(listOpt.get());
}
@Test(expected = NullPointerException.class)
public void ofThrowException() {
Optional<String> opt = Optional.of(null);
assertFalse(opt.isPresent());
}
@Test
public void ofNullable() {
Optional<String> opt = Optional.ofNullable("Beef");
System.out.println(opt);
assertTrue(opt.isPresent());
System.out.println(opt.get());
Optional<Integer> intOpt = Optional.ofNullable(147);
System.out.println(intOpt);
assertTrue(intOpt.isPresent());
System.out.println(intOpt.get());
Food food = new Food("Chicken", 2, 1);
Optional<Food> foodOpt = Optional.ofNullable(food);
System.out.println(foodOpt);
assertTrue(foodOpt.isPresent());
System.out.println(foodOpt.get());
List<Food> list = new ArrayList<>();
list.add(food);
list.add(new Food("Duck", 3, 1));
Optional<List<Food>> listOpt = Optional.ofNullable(list);
System.out.println(listOpt);
assertTrue(listOpt.isPresent());
System.out.println(listOpt.get());
}
@Test
public void ofNullableWithNull() {
Optional<String> opt = Optional.ofNullable(null);
System.out.println(opt);
assertFalse(opt.isPresent());
System.out.println(opt.orElse("DEFAULT_VALUE"));
Optional<Integer> intOpt = Optional.ofNullable(null);
System.out.println(intOpt);
assertFalse(intOpt.isPresent());
System.out.println(intOpt.orElse(0));
Optional<Food> foodOpt = Optional.ofNullable(null);
System.out.println(foodOpt);
assertFalse(foodOpt.isPresent());
System.out.println(foodOpt.orElse(null));
Optional<List<Food>> listOpt = Optional.ofNullable(null);
System.out.println(listOpt);
assertFalse(listOpt.isPresent());
System.out.println(listOpt.orElseGet(() -> new ArrayList<Food>()));
}
public static class FoodList {
List<Food> list = null;
public List<Food> getListWithTraditional() {
if (null == this.list) {
this.list = new ArrayList<Food>();
}
return this.list;
}
public List<Food> getListWithOptional() {
return Optional.ofNullable(this.list).orElseGet(ArrayList::new);
}
}
@Test
public void getListWithTraditional() {
FoodList foodList = new FoodList();
List<Food> list = foodList.getListWithTraditional();
System.out.println(list);
assertNotNull(list);
}
@Test
public void getListWithOptional() {
FoodList foodList = new FoodList();
List<Food> list = foodList.getListWithOptional();
System.out.println(list);
assertNotNull(list);
}
}
心得分享
Java Optional Initialize 初始化 Optional 目的是做為 null 值的替代方案,不再使用顯式檢查 null 值判斷, Optional Initialization Java 在應用上相當廣泛,熟悉這些方法的操作,如: empty 、 of 、 ofNullable 等,提供了幾種 Optional 常見範例。