Clean Code that Works.

Java 8 Optional.

Java/이론..2014. 10. 1. 10:14

Java 8에서 추가된 기능인 Optional에 대해서 간단하게 소개된 글이 있어서 공유 합니다.

(http://java.dzone.com/articles/java-8-optional-avoid-null-and)


언제 어디서나 우리를 괴롭히던 Null 과 NPE를 물리칠 수 있다는 군요! +ㅅ+

참고 : java8-optional

함수형 프로그래밍 : 위키설명


Java 8 Optional - Null 및 NullPointerException 둘다 회피하고 코드를 예쁘게 짜기.


Null 과 NPE(NullPointerException), 이를 회피하는 방법에 대한 문서들을 여러방법으로 소개되고 있다. 이런 방법들 보다 Java 8에서 제공하는 Optinal 기능을 사용하면 쉽고, 안전하고, 아름다운 코드로 작성할 수 있다. 이 문서는 다른 옵션 값들이나  유틸리티코드 사용 없이 이를 구현하는 방법을 소개한다.


이전 방법

아래 코드를 살펴보자

1.String unsafeTypeDirName = project.getApplicationType().getTypeDirName();
2.System.out.println(unsafeTypeDirName);

만약 위 코드에서 사용하는 변수들이 null 이면 NPE가 발생된다.

이를 회피 하기 위해서 아래와 같은 코드를 작성했었다. 

01.// 안전하지만 지저분하고 코드가 누락될 수도 있다
02.if (project != null) {
03.ApplicationType applicationType = project.getApplicationType();
04.if (applicationType != null) {
05.String typeDirName = applicationType.getTypeDirName();
06.if (typeDirName != null) {
07.System.out.println(typeDirName);
08.}
09.}
10.}

NPE를 발생 시키지는 않지만 코드가 지저분하고 null 체크가 누락되기 쉽다.

Java 8
Java 8에서 제공하는 Optional 기능을 사용해서 재구현해보자

01.
02.Optional<Project> optionalProject = Optional.ofNullable(project);
03. 
04.// 안전하고 Java 8을 사용했지만 지저분하고 여전히 코드가 누락될 가능성이 있다
05.if (optionalProject.isPresent()) {
06.ApplicationType applicationType = optionalProject.get().getApplicationType();
07.Optional<ApplicationType> optionalApplicationType = Optional.ofNullable(applicationType);
08.if (optionalApplicationType.isPresent()) {
09.String typeDirName = optionalApplicationType.get().getTypeDirName();
10.Optional<String> optionalTypeDirName = Optional.ofNullable(typeDirName);
11.if (optionalTypeDirName.isPresent()) {
12.System.out.println(optionalTypeDirName);
13.}
14.}

코드가 늘어나고 더 개선된 내용이 없어 보인다. 

Functional Interface를 사용해 Optional의 진짜 힘을 사용해보자!

1.// 안전하고 깔끔하다
2.Optional<String> optionalTypeDirName = optionalProject
3..map(project -> project.getApplicationType())
4..map(applicationType -> applicationType.getTypeDirName());
5.optionalTypeDirName.ifPresent(typeDirName -> System.out.println(typeDirName));

map()은 한상 Optional 객체를 리턴하기 때문에 Null은 허용되지 않고 
IfPresent()는 해당 객체에 값이 있어야 실행되고 기본값 같은것은 전혀 세팅되어 있지 않다.

위 코드를 조금 더 줄여 보면 아래와 같이 작성 할 수있다.

1.// 안전하고 여전히 깔끔하다
2.Optional<String> optionalTypeDirName2 = optionalProject
3..map(Project::getApplicationType)
4..map(ApplicationType::getTypeDirName);
5.optionalTypeDirName2.ifPresent(System.out::println);

결론
Optional을 사용한다면 null 관련된 작업 및 이를 회피하기 위한 작업을 진행 별도로 하지 않아도 된다. 
레거시 코드에서 사용되는 값들이 Null이 될 수 있다면 가능한 빨리 Optional 기능을 사용하길 바란다.