前言

Java 8 引入了 Optional 類別, 用來優雅地處理可能為 null 的值, 避免 NullPointerException. 這篇文章介紹 Optional 的基本用法與常見應用場景.

Optional 是什麼?

Optional 是值的容器, 只有兩種狀態: 不是有值就是沒值. 將輸入的值產生為 Optional 物件, 這時 Optional 物件即為該值的容器. 若要取回該值, 必須使用 get() 方法.

將值轉為 Optional 的方法

  • of(): 接受 非 null 的值 並回傳 Optional 物件
  • ofNullable(): 可以接受 null 的值, 回傳 Optional 物件

取得 Optional 內的值的方法

  • get(): 如果值存在就回傳這個值, 否則就丟出 NoSuchElementException
  • orElse(T other): 如果值存在就回傳這個值, 否則回傳 other
  • orElseGet(Supplier<? extends T> other): 如果值存在就回傳這個值, 否則就呼叫 other 並回傳它的結果
  • orElseThrow(Supplier<? extends X> exceptionSupplier): 如果值存在就回傳這個值, 否則就丟出由 exceptionSupplier 建立的例外

常用範例

Repository 可以直接用 Optional, 這樣就可以避免資料庫互動時回 null 造成錯誤.

public interface DemoRepository extends JpaRepository<DemoEntity, String> {

    Optional<DemoEntity> findByGuid(String guid);
}

Service 就可以依照以下方法使用它.

@RequiredArgsConstructor
@Service
@Slf4j
public class DemoService {

    @Autowired
    private DemoRepository demoRepository;

    public GuidRs getGuidDetail(GuidRq param) {

        GuidRs guidRs = new GuidRs();

        // 利用 Optional 承接資料庫沒有這個值為 null
        var optEntity = demoRepository.findByGuid(param.getGuid());

        // 再用 isPresent() 方法判斷是否為 null
        if (optEntity.isPresent()) {

            // get() 可以取得 Optional 裡的物件
            DemoEntity temp = optEntity.get();

            guidRs.setSomething(temp.getSomething());
        }

        return guidRs;
    }
}

總結

Optional 提供了優雅的方式來處理可能為 null 的值, 避免 NullPointerException. 善用 Optional 可以讓程式碼更加安全且易讀.

參考資料