일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- gdg
- assertj
- Spring
- g1
- RabbitMQ
- 비동기
- spring boot
- 시큐리티
- OAuth
- apache
- Security
- tomcat
- jvm
- JWT
- clean code
- 스프링 부트
- load balancing
- 권한
- java
- 리팩토링
- JPA
- 페이스북
- Producer
- oauth2
- Refactoring
- GC
- 스프링
- 스프링부트
- 페이징
- 클린코드
- Today
- Total
허원철의 개발 블로그
Java - Optional API 본문
이번 편은 JAVA 8에서 새롭게 등장한 Optional에 대한 간단한 예제 글 입니다.
왜 Optional을 사용해야 하는가...?
- 흔히 개발을 하다보면 null 처리에 대해 정말 난감한 부분이 많습니다. 예를 들면,
1 2 3 4 5 | String name = "wonchul"; if(name != null && !"".equals(name)) { // ... } | cs |
위와 같이 조건처리가 꼭 들어가고, default value 가 필요하면 또 적당한 코드 작업이 필요합니다. 물론 유틸 클래스를 만들어서 처리 할 수 있습니다. (Spring에선 StringUtils 클래스를 제공하여 유용하게 쓸 수 있습니다.)
Optional에서는 이런 부분을 람다식 표현을 더해 조금 더 간결하고 가독성을 높일 수 있습니다. 예제는 람다식 표현과 assertj를 이용한 test code이니 참고하시고 보시면 되겠습니다.
Optional 생성
1 2 3 | Optional<String> opName = Optional.empty(); Optional<String> opName = Optional.of("wonchul"); Optional<String> opName = Optional.ofNullable("wonchul"); | cs |
1) null이 들어갑니다.
2) "wonchul" 이라는 문자열을 넣습니다.
3) "wonchul" 이라는 문자열을 넣습니다.( ※ null을 넣어도 가능합니다.)
Optional get
- get() 를 이용해서 제네릭에 표기된 자료형의 값을 가져올 수 있습니다.
1 2 | Optional<String> opName = Optional.of("wonchul"); opName.get(); // wonchul | cs |
※ 값이 빈 경우 NoSuchElementException이 발생합니다.
Optional isPresent
- isPresent() 를 이용하여 값이 비었는지 알 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 | @Test public void test_isParent() { // Optional<String> name = Optional.of("wonchul"); Optional<String> name = Optional.ofNullable(null); if(name.isPresent()) { assertThat(name).isPresent(); } else { assertThat(name).isNotPresent(); // call } } | cs |
Optional ifPresent
- ifPresent() 를 이용하여 값이 있을 경우, 원하는 처리를 할 수 있도록 도와줍니다.
1 2 3 4 5 6 | @Test public void test_ifParent() { Optional<String> name = Optional.of("wonchul"); name.ifPresent(System.out::println); // wonchul } | cs |
Optional isElse, isElseGet, isElseThrow
- isElseXXX() 를 이용하여 Default 처리를 하거나, exception를 보내버릴 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Test public void test_orElse() { Optional<String> name = Optional.of("wonchul"); Optional<String> nameNullable = Optional.ofNullable(null); // ... call defaultValue() System.out.println("orElse => " + name.orElse(defaultValue())); System.out.println("orElseGet => " + name.orElseGet(() -> defaultValue())); // ... call defaultValue() System.out.println("orElse => " + nameNullable.orElse(defaultValue())); // ... call defaultValue() System.out.println("orElseGet => " + nameNullable.orElseGet(() -> defaultValue())); // System.out.println("orElseThrow => " + name.orElseThrow(NullPointerException::new)); } private String defaultValue() { System.out.println("call defaultValue()"); return "default name : wonchul"; } | cs |
※ orElse, orElseGet 차이점은 defaultValue() 함수를 무조건 호출 유무에 차이입니다. defaultValue()를 호출하는데 많은 비용이 든다면, orElseGet을 이용하는 것이 더 효율적일 것 입니다.
Example
- 오라클 기사(?)에 있는 예제를 참고한 것 입니다. (참고 : http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html)
- 다음과 같은 구조에서 version을 가져올 때, 코드 작성을 예로 들어보겠습니다.
1) optional 사용하지 않은 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private final String getDefaultVersion() { return "UNKNOWN"; } @SuppressWarnings("unused") @Test public void test_basic() { Computer computer = null; String version = getDefaultVersion(); if(computer != null) { if(computer.getSoundCard() != null) { if (computer.getSoundCard().getUsb() != null) { version = computer.getSoundCard().getUsb().getVersion(); } } } assertThat( version ).isEqualTo(getDefaultVersion()); } | cs |
- 중첩 if문을 사용하지 않아도 되지만, 결론적으로는 if문을 3번 사용하게 되면서 코드가 길어집니다.
2) optional 사용한 경우
1 2 3 4 5 6 7 8 9 10 11 12 | @Test public void test_expansion() { Optional<OpComputer> opComputer = Optional.empty(); assertThat( opComputer .flatMap(OpComputer::getSoundCard) .flatMap(OpSoundCard::getUsb) .flatMap(OpUsb::getVersion) .orElseGet(() -> getDefaultVersion()) ).isEqualTo(getDefaultVersion()); } | cs |
- flatMap과 orElseGet를 조합하여 깔끔한 코드를 만들어낼 수 있습니다.
※ JAVA 8부터는 유용한 메소드가 많습니다. ( filter, steam, flatmap, map.. 등등 ) 여러 조합으로 섞어쓰면 기존에 JAVA 8미만에서의 코드보다 가독성이 높은 코드를 만들 수 있습니다.
참고
- http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
'java' 카테고리의 다른 글
Java - Compare GC (406) | 2017.03.07 |
---|---|
Java - GC (Garbage Collection) (420) | 2017.03.05 |
Java - time package(LocalTime, LocalDate, LocalDateTime,...) (398) | 2017.02.07 |
Java - JUnit & AssertJ (406) | 2016.12.05 |
Java - Stream API (404) | 2016.12.05 |