๐ 1. ์ต์ ๋ ๊ฐ๋
Optional<T>๋ null์ด ์๋ T ํ์ ์ฐธ์กฐ๋ฅผ ํ๋ ๋ด๊ฑฐ๋, ํน์ ์๋ฌด๊ฒ๋ ๋ด์ง ์์ ์ ์๋ค. ๋ณดํต์ T๋ฅผ ๋ฐํํด์ผ ํ์ง๋ง ํน์ ์กฐ๊ฑด์์๋ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์์ผ ํ ๋ T ๋์ Optional<T>๋ฅผ ๋ฐํํ๋๋ก ์ ์ธํ๋ฉด ๋๋ค.
์ต์ ๋์ ๋ฐํํ๋ ๋ฉ์๋๋ ์์ธ๋ฅผ ๋์ง๋ ๋ฉ์๋๋ณด๋ค ์ ์ฐํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ฐ๋ฉฐ, null์ ๋ฐํํ๋ ๋ฉ์๋๋ณด๋ค ์ค๋ฅ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
์ปฌ๋ ์ ์ ์ต๋๊ฐ์ ๊ตฌํ๋ ๋ฉ์๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด Optional๋ก ํํํ ์ ์๋ค.
// Optional์ ์ฌ์ฉํ์ง ์์ ๊ฒฝ์ฐ
public static <E extends Comparable<E>> E max(Collection<E> c) {
if(c.isEmpty())
throw new IllegalArgumentException("๋น ์ปฌ๋ ์
");
E result = null;
for(E e : c)
if(result == null || e.compareTo(result) > 0)
result = Objects.requireNonNull(e);
return result;
}
// Optional์ ์ฌ์ฉํ ๊ฒฝ์ฐ
public static <E extends Comparable<E>> Optional<E> max(Collection<E> c) {
if(c.isEmpty())
return Optional.empty();
E result = null;
for(E e : c)
if(result == null || e.compareTo(result) > 0)
result = Objects.requireNonNull(e);
return Optional.of(result);
}
๋น ์ต์ ๋์ Optional.empty()๋ก ๋ง๋ค๊ณ , ๊ฐ์ด ๋ ์ต์ ๋์ Optional.of(value)๋ก ์์ฑํ๋ค. ๋ง์ฝ, Optional.of(value)์ null์ ๋ฃ์ผ๋ฉด NullPointException์ ๋์ง๋ ์ฃผ์ํ์.
์ต์ ๋์ ๋ฐํ ๊ฐ์ด ์์ ์๋ ์์์ API ์ฌ์ฉ์์๊ฒ ๋ช ํํ ์๋ ค์ค๋ค. ์ฆ, ๋ฉ์๋๊ฐ ์ต์ ๋์ ๋ฐํํ๋ฉด ํด๋ผ์ด์ธํธ๋ ๊ฐ์ ๋ฐ์ง ๋ชปํ์ ๋ ์ทจํ ํ๋์ ์ ํํด์ผ ํ๋ค.
๐ 2. ์ต์ ๋ ํ์ฉ
์ต์ ๋์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด์.
๐ 1. orElse
String lastWordInLexicon = max(words).orElse("๋จ์ด ์์...");
๊ฐ์ ๋ฐ์ง ๋ชปํ์ ๋ ์ทจํ ํ๋์ผ๋ก ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ ์ ์๋ค.
๐ 2. orElseThrow
Toy myToy = max(toys).orElseThrowTemperTantrumException::new);
๊ฐ์ ๋ฐ์ง ๋ชปํ์ ๋ ์ทจํ ํ๋์ผ๋ก ์ํฉ์ ๋ง๋ ์์ธ๋ฅผ ๋์ง ์ ์๋ค. ์ฝ๋์์ ์ฒ๋ผ ์์ธ ํฉํฐ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์์ธ๊ฐ ์ค์ ๋ก ๋ฐ์ํ์ง ์๋ ํ ์์ธ ์์ฑ ๋น์ฉ์ ๋ค์ง ์๋๋ค.
๐ 3. get
Element lastNobleGas = max(Elements.NOBLE_GASES).get();
๊ฐ์ด ํญ์ ์ฑ์์ ธ ์๋ค๊ณ ํ์ ํ๋ค๋ฉด ๋ฐ๋ก ๊ฐ์ ๊บผ๋ด ์ธ ์ ์๋ค. ๋ฌผ๋ก ์๋ชป ํ๋จํ ๊ฒ์ด๋ผ๋ฉด NoSuchElementException์ด ๋ฐ์ํ๋ค.
๐ 4. orElseGet
Connection connection = getConnection(dataSource).orElseGet(() -> getLocalConnection());
๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๋ ๋น์ฉ์ด ์์ฃผ ์ปค์ ๋ถ๋ด์ด ๋ ๊ฒฝ์ฐ์๋ Supplier<T>๋ฅผ ์ธ์๋ก ๋ฐ๋ orElseGet์ ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ฐ์ด ์ฒ์ ํ์ํ ๋ Supplier<T>๋ฅผ ์ฌ์ฉํด ์์ฑํ๋ฏ๋ก ์ด๊ธฐ ์ค์ ๋น์ฉ์ ๋ฎ์ถ ์ ์๋ค.
๐ 5. ๊ทธ ์ธ
๋ ํน๋ณํ ์ฐ์์ ๋๋นํ ๋ฉ์๋๋ filter, map, flatMap, ifPresent๊ฐ ์๋ค.
// isPresent
Optional<ProcessHandle> parentProcess = ph.parent();
System.out.println("๋ถ๋ชจ PID: " + (parentProcess.isPresent() ?
String.valueOf(parentProcess.get().pid()) : "N/A"));
// map
System.out.println("๋ถ๋ชจ PID: " +
ph.parent().map(h -> string.valueOf(h.pid()))).orElse("N/A");
// filter
streamOfOptionals
.filter(Optional::isPresent)
.map(Optional::get)
// flatMap
streamOfOptionals
.flatMap(Optional::stream)
๐ 3. ์ต์ ๋์ ์ฌ์ฉํ๋ฉด ์ ๋๋ ๊ฒฝ์ฐ
๋ฐํ๊ฐ์ผ๋ก ์ต์ ๋์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฌด์กฐ๊ฑด ์ข์ ๊ฒ์ ์๋๋ค. ์๋์ ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ์ฌ ์ฌ์ฉํ๋๋ก ํ์.
- ์ปฌ๋ ์
, ์คํธ๋ฆผ, ๋ฐฐ์ด, ์ต์
๋ ๊ฐ์ ์ปจํ
์ด๋ ํ์
์ ์ต์
๋๋ก ๊ฐ์ธ๋ฉด ์ ๋๋ค.
๋น Optional<List<T>>๋ฅผ ๋ฐํํ๊ธฐ๋ณด๋ค๋ ๋น List<T>๋ฅผ ๋ฐํํ๋ ๊ฒ ์ข๋ค. ๋น ์ปจํ ์ด๋๋ฅผ ๊ทธ๋๋ก ๋ฐํํ๋ฉด ํด๋ผ์ด์ธํธ์ ์ต์ ๋ ์ฒ๋ฆฌ ์ฝ๋๋ฅผ ๋ฃ์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ด๋ค. - ์ต์ ๋ ๋ฐํ์๋ ์ฑ๋ฅ ์ ํ๊ฐ ๋ค๋ฐ๋ฅด๋, ์ฑ๋ฅ์ ๋ฏผ๊ฐํ ๋ฉ์๋๋ผ๋ฉด null์ ๋ฐํํ๊ฑฐ๋ ์์ธ๋ฅผ ๋์ง๋ ํธ์ด ๋์ ์ ์๋ค.
- ์ต์
๋์ ์ปฌ๋ ์
์ ํค, ๊ฐ, ์์๋ ๋ฐฐ์ด์ ์์๋ก ์ฌ์ฉํ๋ ๊ฒ ์ ์ ํ ์ํฉ์ ๊ฑฐ์ ์๋ค.
์ต์ ๋์ ๋งต์ ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ค๊ณ ์๊ฐํด ๋ณด์. ๋งต ์์ ํค๊ฐ ์๋ค๊ณ ๋ํ๋ด๋ ๋ฐฉ๋ฒ์ 'ํค ์์ฒด๊ฐ ์๋ ๊ฒฝ์ฐ'์ 'ํค๋ ์์ง๋ง ๊ทธ ํค๊ฐ ์์ด ๋น ์ต์ ๋์ธ ๊ฒฝ์ฐ'๋ค. ์ด๋ ๋ณต์ก์ฑ๋ง ๋์ฌ์ ํผ๋๊ณผ ์ค๋ฅ ๊ฐ๋ฅ์ฑ์ ํค์ด๋ค.
ํด๋น ๊ธ์ Joshua Bloch ๋์ 'Effective Java 3/E'๋ฅผ ์ฐธ๊ณ ํ์์ต๋๋ค.