-
Java8. OptionalBackEnd/Java 2022. 1. 22. 08:13반응형
Optional은 비어있을 수도 있고, 오직 값 한개가 들어있을 수도 있는 컨테이너 인스턴스입니다. 메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로도 사용이 가능하지만 리턴값으로만 사용하도록 권장합니다. 프리미티브 타입용 Optional(OptionalInt, OptionalLong 등)은 따로 존재하며, Collection, Map, Stream, Array, Optional은 자체적으로 비어있는 것을 확인할 수 있기 때문에 Optional로 감싸지 않습니다.
Person과 Info 도메인이 존재할 때 아래와 같이 호출을 하게 되면 NullPointerException이 발생합니다.
public class Person { private int age; private String name; private Info info; public Person(int age, String name) { this.age = age; this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } }
public class Info { private int height; public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }
public class OptionalClass { public static void main(String[] args) { Person person = new Person(6, "Daol"); Info info = person.getInfo(); System.out.println(info.getHeight()); /* [결과] Exception in thread "main" java.lang.NullPointerException at OptionalClass.main(OptionalClass.java:6) */ } }
이러한 문제를 해결하기 위해 if(info != null) System.out.println(info.getHeight()); 같이 적용할 수 있지만 누락할 가능성이 존재합니다. Optional을 적용한 코드는 아래와 같습니다.
import java.util.Optional; public class Person { ... 생략 ... public Optional<Info> getInfo() { return Optional.ofNullable(info); } ... 생략 ... }
import java.util.Optional; public class OptionalClass { public static void main(String[] args) { Person person = new Person(6, "Daol"); Optional<Info> info = person.getInfo(); info.ifPresent(i -> System.out.println(i.getHeight())); } }
Optional API
- Optional 만들기: Optional.of() / Optional.ofNullable() / Optional.empty()
- Optional 값 존재여부 확인: isPresent() / isEmpty() (Java 11부터 제공)
- Optional에 있는 값 가져오기: get() / ifPresent(Consumer) / orElse(T) / orElseGet(Supplier) / orElseThrow()
- Optional 필터링: Optional filter(Predicate)
- Optional 변환: Optional map(Function) /
Optional flatMap(Function): Optional 안에 들어있는 인스턴스가 Optional인 경우 사용
아래 샘플코드를 참고하여 사용하면 됩니다.
import java.util.ArrayList; import java.util.List; import java.util.Optional; public class OptionalClass { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person(6, "Daol")); list.add(new Person(4, "Iden")); list.add(new Person(3, "Jena")); // 이름에 "a"가 포함된 첫번째를 찾습니다. Optional<Person> optional = list.stream() .filter(l -> l.getName().contains("a")) .findFirst(); /* System.out.println(optional.get().getName()); // [결과]: Daol (단, 값이 없는 경우 NoSuchElementException) */ // 값이 있는 경우만 출력합니다. optional.ifPresent(o -> System.out.println(o.getName())); // 값이 존재하는지 확인합니다. boolean present = optional.isPresent(); System.out.println(present); // [결과]: true // Optional에 값이 있으면 가져오고 없는 경우 새로운 인스턴스를 만듭니다. Person person = optional.orElseGet(OptionalClass::createNew); System.out.println(person.getName()); // [결과]: Daol // Optional에 값이 있으면 가져오고 없는 경우 에러를 던집니다. Person optionalThrow = optional.orElseThrow(); // "A"로 시작하는 이름으로 필터링 합니다. Optional<Person> optionalFilter = optional .filter(l -> l.getName().startsWith("A")); System.out.println(optionalFilter.isEmpty()); // [결과]: true // 이름에 성을 붙여 새로운 Optional을 만듭니다. Optional<String> newOptional = optional.map(o -> o.getName() + " Kim"); newOptional.ifPresent(System.out::println); // [결과]: Daol Kim } private static Person createNew() { return new Person(35, "Hanseom"); } }
반응형'BackEnd > Java' 카테고리의 다른 글
Multi-Thread Programming (0) 2022.01.23 Java8. Date-Time API (0) 2022.01.22 Java8. 스트림 (Stream) (0) 2022.01.22 Java8. 기본 메소드 (Default Method)와 스태틱 메소드 (Static Method) (0) 2022.01.22 Java8. 메소드 레퍼런스 (Method Reference) (0) 2022.01.20