Initialize Optional in Java - Java 147

Initialize Optional in Java – Java 147

Initialize 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 常見範例。

發佈留言