Optional Class Example
Reference : http://javaiyagi.tistory.com/443
http://multifrontgarden.tistory.com/128
http://asfirstalways.tistory.com/354
Optional Class In Java 8
=> 하스켈, 스칼라 등의 함수형 언어에서 사용되고 있는 '선택형 값' 개념의 영향을 받아 Optional<T>라는 새로운 클래스를 제공한다.
=> 값이 없는 상황을 모델링 하는 것
- Optional은 선택형 값을 캡슐화 하는 클래스이다. 값이 존재하면 그 값을 감싼다.
- 값이 없는 경우에는 Optional.empty() 메서드로 Optional을 반환한다.
- empty 메서드는 Optional의 싱글턴 인스턴스를 반환하는 정적 팩토리 메서드이다.
null vs Optional.empty()
- null을 참조하면 NPE 발생!
- empty 메서드의 반환 값은 Optional이라는 객체 !
어떻게 사용할 것인가?
잠재적으로 null이 될 수 있는 대상을 Optional로 감싼다.
// java 8 이전 code
Object value = map.get("key");
// java 8 code
Optional<Object> value = Optional.ofNullable(map.get("key"));
In General
public class Computer {
private Soundcard soundcard;
public Soundcard getSoundcard() {...}
...
}
public class Soundcard {
private USB usb;
public USB getUSB() {...}
}
public class USB{
public String getVersion() {...}
}
String version = computer.getSoundcard().getUSB().getVersion();
# Enable: NullPointerException
String version = "UNKNOWN";
// Deep Doubt (깊은 의심) 패턴
if (computer != null) {
Soundcard soundcard = computer.getSoundcard();
if (soundcard != null) {
USB usb = soundcard.getUSB();
if (usb != null) {
version = usb.getVersion();
}
}
}
// 같은 코드
if (computer != null
&& computer.getSoundcar() != null
&& computer.getSoundcar().getUSB() != null)
version = computer.getSoundcard().getUSB().getVersion();
In Optional class
Optional API
- void ifPresent(Consumer<T>)
- Optional<T> filter(Predicate<T>)
- Optional<U> map(Function<T, U>)
- T get()
- T orElse()
- TorElseGet(Supplier<T>)
- TorElseThrow(Supplier<U>)
public class Computer {
private Optional<Soundcard> soundcard;
public Optional<Soundcard> getSoundcard() {...}
...
}
public class Soundcard {
private Optional<USB> usb;
public Optional<USB> getUSB() {...}
}
public class USB {
public String getVersion() {...}
}
String name = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNONW");
General vs Optional
// general
Soundcard soundcard = ...;
if (soundcard != null)
System.out.println(soundcard);
// optional
Optional<Soundcard> soundcard = ...;
soundcard.ifPresent(System.out::println);
// general
Soundcard soundcard = maybeSoundcard != null ? maybeSoundcard : new Soundcard("basic_soundcard");
// optional
Soundcard soundcard = maybeSoundcard.orElse(new Soundcard("basic_sound_card"));
// general
USB usb = ...;
if (usb != null && "3.0".equals(usb.getVersion()))
System.out.println("ok");
// optional
Optional<USB> maybeUSB = ...;
maybeUSB.filter(usb-> "3.0".equals(usb.getVersion())
.ifPresent(() -> System.out.println("ok"));