Optional

Java 8에 μƒˆλ‘œ 생긴 μΈν„°νŽ˜μ΄μŠ€λ‘œ 라이브러리 λ©”μ„œλ“œκ°€ λ°˜ν™˜ν•  결과값이 μ—†μŒμ„ λͺ…λ°±ν•˜κ²Œ ν‘œν˜„ν•  ν•„μš”κ°€ μžˆλŠ” κ³³μ—μ„œ μ œν•œμ μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” λ©”μ»€λ‹ˆμ¦˜μ„ μ œκ³΅ν•˜κΈ° μœ„ν•΄ μƒˆλ‘œ 생겨났닀.

Java api doc의 API λ…ΈνŠΈλ₯Ό 보면 λ‹€μŒκ³Ό 같이 μ„€λͺ…ν•˜κ³  μžˆλ‹€. Optional은 주둜 κ²°κ³Ό μ—†μŒμ„ λ‚˜νƒ€λ‚Ό ν•„μš”μ„±μ΄ λͺ…ν™•ν•˜κ³  null을 μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•  수 μžˆλŠ” λ©”μ†Œλ“œ λ°˜ν™˜ μœ ν˜•μœΌλ‘œ μ‚¬μš©ν•˜λ„λ‘ κ³ μ•ˆλ˜μ—ˆλ‹€. μœ ν˜•μ΄ μ˜΅μ…˜μΈ λ³€μˆ˜ μžμ²΄λŠ” null이 μ•„λ‹ˆλ―€λ‘œ 항상 μ˜΅μ…˜ μΈμŠ€ν„΄μŠ€λ₯Ό κ°€λ¦¬μΌœμ•Ό ν•œλ‹€.

Optional을 μ˜¬λ°”λ₯΄κ²Œ μ‚¬μš©ν•˜κΈ°

1. Optional λ³€μˆ˜μ— null λŒ€μ‹  Optional.empty() μ‚¬μš©

Optional<Car> optionalCar = null;

Optional<Car> optionalCar = Optional.empty();

2. Optional 값을 κΊΌλ‚΄μ“°κΈ° 전에 값이 μžˆλŠ”μ§€ ν™•μΈν•˜κΈ°

Optional<Car> optionalCar = Optional.empty();

Car car = optionalCar.get(); //NoSuchElementException λ°œμƒ

Optional은 값이 λΉ„μ–΄μžˆμ„ μˆ˜λ„ 있기 λ•Œλ¬Έμ— μ‚¬μš©ν•˜κΈ°μ „μ— μ‘΄μž¬ν•œλ‹€λŠ” 것을 증λͺ…ν•΄μ•Ό ν•˜λŠ”λ° μΌλ°˜μ μœΌλ‘œλŠ” isPresent()후에 get()을 μ‚¬μš©ν•  수 μžˆμ§€λ§Œ μ½”λ“œλ„ κΈΈμ–΄μ§€κ³  ν•œλ²ˆμ— μ‚¬μš©ν•  수 μžˆλŠ” APIλ₯Ό μ œκ³΅ν•˜κΈ° λ•Œλ¬Έμ— 이λ₯Ό μ‚¬μš©ν•΄λ³΄μž.

//isPresent - get
if(optionalCar.isPresent()){
    return optionalCar.get();
}else {
    return null;
}

//orElse
return optionalCar.orElse(null);

//orElseGet
return optionalCar.orElseGet(() -> null);

orElseGet()은 Supplierλ₯Ό 인자둜 λ°›μœΌλ©°, 값이 μ—†μ„λ•Œμ— ν•΄λ‹Ή supplierκ°€ μˆ˜ν–‰λœλ‹€. ν•˜μ§€λ§Œ orElse()λŠ” Optional둜 감싸고 μžˆλŠ” κ°μ²΄νƒ€μž…μ„ 인자둜 λ°›μœΌλ©° 값이 μžˆλ”λΌλ„ λ‚΄λΆ€κ°€ μˆ˜ν–‰λ˜κ³  μ‚¬μš©λ˜μ§€ μ•ŠλŠ” 경우 ν•΄λ‹Ή 객체λ₯Ό μ§€μš°κ²Œ λ˜μ–΄ ν•„μš”μ—†λŠ” μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•œλ‹€.

예λ₯Ό λ“€μ–΄ μœ„μ™€ 같은 μ½”λ“œλ₯Ό μž‘μ„±ν–ˆμ„λ•Œ optStr은 null이 μ•„λ‹ˆλΌ new String("hi1")κ°€ μ‹€ν–‰λ˜μ§€ μ•Šμ„ 것 κ°™μ§€λ§Œ λ°”μ΄νŠΈμ½”λ“œλ₯Ό 보면 μƒˆλ‘œ λ¬Έμžμ—΄μ„ μƒμ„±ν–ˆλ‹€κ°€ POPν•˜λŠ” 것을 λ³Ό 수 있고, orElseGet()은 μš°λ¦¬κ°€ lambdaμ—μ„œ λ΄€λ˜κ²ƒμ²˜λŸΌ static λ©”μ„œλ“œλ‘œ μƒμ„±ν•˜μ—¬ ν˜ΈμΆœλ˜λŠ” 타이밍에 이λ₯Ό μ‹€ν–‰ν•΄ 객체λ₯Ό μƒμ„±ν•˜λŠ” 것을 λ³Όμˆ˜μžˆμ–΄ orElseλŠ” ν•„μš”μ—†λŠ” μ˜€λ²„ν—€λ“œμ— μ£Όμ˜ν•΄μ•Όν•œλ‹€. ν•˜μ§€λ§Œ λ°˜λ“œμ‹œ 이미 μƒμ„±λ˜μ–΄μžˆλŠ” 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” 것이라면 orElse()λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 쒋을 μˆ˜λ„ μžˆλ‹€.

μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό ν•˜λŠ” κ²½μš°μ—λ„ isPresent()λ₯Ό ν†΅ν•œ μ˜ˆμ™Έμ²˜λ¦¬λ³΄λ‹€λŠ” orElseThrow()λ₯Ό μ΄μš©ν•˜μ—¬ μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό ν•˜λŠ” 것이 λ°”λžŒμ§ν•˜λ‹€. 인자둜 Supplierλ₯Ό 톡해 νŠΉμ • Exception을 던질 수 μžˆλŠ”λ° 아무것도 μ£Όμ§€ μ•ŠμœΌλ©΄ 기본적으둜 NoSuchElementException을 λ˜μ§„λ‹€.

3. Optional이 μžˆμ„λ•Œλ§Œ 이λ₯Ό μ†ŒλΉ„ν•˜μ—¬ 무언가λ₯Ό ν• λ•ŒλŠ” ifPresent()λ₯Ό ν™œμš©

4. μ»¬λ ‰μ…˜μ€ OptionalλŒ€μ‹  λΉ„μ–΄μžˆλŠ” μ»¬λ ‰μ…˜μ„ μ‚¬μš©ν•˜μž.

5. μ»¬λ ‰μ…˜μ€ Optional둜 κ°μ‹Έμ§€λ§μž.

μ»¬λ ‰μ…˜ μžμ²΄κ°€ 데이터λ₯Ό 감싼 ν˜•νƒœμ˜ 객체이고 이도 μΆ©λΆ„ν•œ APIλ₯Ό μ œκ³΅ν•˜κΈ° λ•Œλ¬Έμ— ν•œλ²ˆλ” Optional둜 감싸면 ν•„μš”μ—†λŠ” μ˜€λ²„ν—€λ“œκ°€ λ°œμƒν•œλ‹€. JPA의 λ©”μ„œλ“œλ₯Ό μƒμ„±ν• λ•Œλ„ JPA자체적으둜 λΉ„μ–΄μžˆλŠ” μ»¬λ ‰μ…˜μ„ λ°˜ν™˜ν•΄μ£Όλ―€λ‘œ Optional둜 κ°μŒ€ ν•„μš”κ°€ μ—†λ‹€.

6. μ»¬λ ‰μ…˜,Map의 μ›μ†Œλ‘œ Optional을 μ‚¬μš©ν•˜μ§€ 말자.

7. 단일 값을 μ–»κΈ° μœ„ν•œ λͺ©μ μœΌλ‘œ λ©”μ„œλ“œ 체이닝을 ν•˜μ§€λ§μž.

Optional을 μ‚¬μš©ν•˜λŠ” 것은 κ²°κ΅­ λ˜ν•˜λ‚˜μ˜ 래퍼객체λ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμ΄λ―€λ‘œ λ‹¨μˆœν•œ 둜직이라면 κ·Έλƒ₯ μ½”λ”©ν•˜μž. ꡬ관이 λͺ…κ΄€μ΄λΌν–ˆλ‹€.

8. Optional을 ν•„λ“œλ‘œ μ‚¬μš©ν•˜μ§€λ§μž.

Optional은 μ• μ΄ˆμ— ν•„λ“œλ‘œ μ‚¬μš©ν•  λͺ©μ μœΌλ‘œ λ§Œλ“€μ–΄μ§€μ§€ μ•Šμ•„ Serializable도 κ΅¬ν˜„ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— μ‚¬μš©μ„ μ§€μ–‘ν•΄μ•Ό ν•œλ‹€.

9. Optional을 λ©”μ„œλ“œ,μƒμ„±μž 인자둜 μ‚¬μš©ν•˜μ§€λ§μž.

μ΄λŸ¬ν•œ 방법은 λΆˆν•„μš”ν•˜κ²Œ μ½”λ“œλ₯Ό λ³΅μž‘ν•˜κ²Œ ν•  λΏμ•„λ‹ˆλΌ 이λ₯Ό ν˜ΈμΆœν•˜λŠ” μͺ½μ—μ„œλ„ Optional 생성을 κ°•μ œν•˜κ²Œ ν•˜λŠ” 것이닀. λ˜ν•œ, Optional은 ν•˜λ‚˜μ˜ 객체둜 이λ₯Ό ν˜ΈμΆœν•˜λŠ” 것이 κ²°μ½” λΉ„μš©μ΄ μ €λ ΄ν•˜μ§€ μ•Šλ‹€.

10. null이 ν™•μ‹€ν•˜λ©΄ ofNullable()이 μ•„λ‹Œ of()λ₯Ό μ‚¬μš©ν•˜μž.

ofNullable은 λ‚΄λΆ€μ μœΌλ‘œ 보면 μ‚Όν•­μ—°μ‚°μžλ₯Ό 톡해 λΉ„μ–΄μžˆμ§€ μ•ŠλŠ” 경우 ofλ₯Ό ν˜ΈμΆœν•˜λŠ” 것을 λ³Ό μˆ˜μžˆλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ΄λŸ¬ν•œ 연산을 μ‘°κΈˆμ΄λΌλ„ 쀄일 수 있기 λ•Œλ¬Έμ— ofλ₯Ό μ‚¬μš©ν•˜μž.

11. Optional의 νƒ€μž…μ΄ Primitiveνƒ€μž…μ΄λ©΄ OptionalInt,OptionalLong, OptionalDouble을 μ‚¬μš©ν•˜μž

λ‚΄λΆ€μ μœΌλ‘œ Integer.valueOf()λ₯Ό 톡해 ν•œλ²ˆ boxing이 μΌμ–΄λ‚˜λŠ” 것을 λ³Ό 수 있고 또 이λ₯Ό μ‚¬μš©ν• λ•Œ unboxing이 μΌμ–΄λ‚˜κΈ° λ•Œλ¬Έμ— OptionalIntλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€.

12. Optional을 λ¦¬ν„΄ν•˜λŠ” λ©”μ„œλ“œμ—μ„œ null을 λ¦¬ν„΄ν•˜μ§€ 말자.

λ‹Ήμ—°ν•œκ±°μ§€λ§Œ Optional도 객체이기 λ•Œλ¬Έμ— null을 리턴이 κ°€λŠ₯ν•œλ° μ΄λ ‡κ²Œ λ¦¬ν„΄ν•˜κ²Œ 되면 Optional을 μ‚¬μš©ν•˜λŠ” 것이 μ˜λ―Έκ°€ μ—†κΈ° λ•Œλ¬Έμ— null을 λ¦¬ν„΄ν•˜μ§€ 말자.


Reference

https://dzone.com/articles/using-optional-correctly-is-not-optional

Last updated