[JAVA Optional] Optional에 대해 알아보자

준커·2023년 5월 7일
1

JAVA 8

목록 보기
5/5
post-thumbnail

좀 더 자세한 내용은 공식문서에서 확인하실 수 있습니다.
java.util.Optional

Optional이란?

JAVA의 영원한 숙적인 NullPointerException을 방지해주는. 즉, null인 값을 참조해도 NullPointerException이 발생하지 않도록 값을 래퍼로 감싸주는 타입입니다.

흔하게 볼 수 있는 곳은 Spring Data JPA를 사용할 때 Repository에서 findById()의 반환값은 Optional 타입입니다.

Member member = memberRepository.findById(memberId);

다음과 같이 코드를 작성하면

Optional 타입이라며 IDE가 잡아줍니다.

실제로 보면 반환타입이 Optional 타입인걸 확인할수 있습니다.

Member member = memberRepository.findById(memberId)
								.orElseThrow(MemberNotFoundException::new)

반환값이 Optional 타입이기 때문에 이렇게 원하는 member를 찾지 못했을 경우 MemberNotFoundException을 발생시켜, NullPointerException을 미리 방지할 수 있습니다.

Optional 사용방법

Optional 공식문서를 보면 Optional 타입은 여러가지 메소드를 제공합니다. 그 메소드들의 사용법을 하나하나 알아봅시다.

Optional 생성 Static 메소드

1. empty()

.empty()

정보

기능: 비어있는 Optional 객체를 생성.
리턴값: Optional<T>

예제코드

// Optional 메소드
Optional<String> empty = Optional.empty();

// 아웃풋
System.out.println(empty.isEmpty()); // true

2. of()

.of(T value)

정보

기능: 전달된 값으로 새로운 Optional 객체를 생성.
리턴값: Optional<T>

예제코드

// Optional 메소드
Optional<String> opt = Optional.of("Hello");

// 아웃풋
System.out.println(opt.get()); // Hello

3. ofNullable()

.ofNullable(T value)

정보

기능: 비어있을 수 있고, 아닐 수도 있는 Optional 객체를 생성.
반환값: Optional<T>

예제코드

// Optional 메소드
String imNull = null;
Optional<String> opt = Optional.ofNullable(imNull);
Optional<String> opt1 = Optional.ofNullable("Hello");

// 아웃풋
System.out.println(opt.isEmpty()); // true
System.out.println(opt1.isEmpty()); // false

Optional 활용 메소드

4. equals()

.equals(Object obj)

정보

기능: Optional 객체의 값을 비교.
리턴값: boolean

예제코드

// 인풋
Optional<String> opt1 = Optional.of("Hello");
Optional<String> opt2 = Optional.of("Hello");
Optional<String> opt3 = Optional.of("World");

// Optional 메소드
boolean isEqual1 = opt1.equals(opt2);
boolean isEqual2 = opt1.equals(opt3);

// 아웃풋
System.out.println(isEqual1); // true
System.out.println(isEqual2); // false

5. filter()

.filter(Predicate<? Super T> predicate)

정보

기능: Optional 객체의 값을 조건에 따라 필터링.
리턴값: Optional

예제코드

// 인풋
Optional<Integer> opt1 = Optional.of(10);
Optional<Integer> opt2 = Optional.of(1);
        
// Optional 메소드
Optional<Integer> filter1 = opt1.filter(num -> num < 5);
Optional<Integer> filter2 = opt2.filter(num -> num < 5);

// 아웃풋
System.out.println(filter1.isEmpty()); // true
System.out.println(filter2.isEmpty()); // false

6. map()

.map(Function<? Super T, ? Extends U> mapper)

정보

기능: Optional 객체 내부의 값을 변환하여 결과를 새로운 Optional 객체로 반환.
리턴값: Optional<U>

예제코드

// 인풋
Optional<String> optional = Optional.of("hello");

// Optional 메소드
Optional<Integer> result = optional.map(s -> s.length());

// 아웃풋
System.out.println(result.get()); // 5

7. flatMap()

.flatMap(Function<? Super T, ? Extends Optional<? Extends U>> mapper)

정보

기능: 중첩된 Optional
리턴값: Optional<U>

예제코드

// 인풋
Optional<String> opt = Optional.of("Hello");
        
// Optional 메소드
Optional<String> flatMappedOpt = opt.flatMap(str -> Optional.of(str.toUpperCase()));

// 아웃풋
System.out.println(flatMappedOpt.get()); // HELLO

map()과 flatMap()의 차이

  • 내부를 까보자!

  • flatMap()은 맵핑 함수 자체가 이미 Optional.

map()과 flatMap()을 각각 보면 flatMap()은 map()에 비해 파라미터가 Optional인 것을 확인할 수 있습니다.

즉, map()은 값의 변환이 간단하게 이루어지는 경우에 사용되며, flatMap()은 중첩된 Optional 객체를 다루거나 매핑 함수 자체가 이미 Optional을 반환하는 경우에 사용.

8. get()

.get()

정보

기본: Optional 객체의 값을 가져옴.
(만약 값이 존재하지 않는 경우, NoSuchElementException이 발생)
리턴값: T

예제코드

// 인풋
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);
        
// 아웃풋
System.out.println(opt1.get()); // Hello
System.out.println(opt2.get()); // NoSuchElementException

9. isEmpty()

.isEmpty()

정보

기능: Optional 객체가 비어있는지 확인.
리턴값: boolean

예제코드

// 인풋
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);

// 아웃풋
System.out.println(opt1.isEmpty()); // false
System.out.println(opt2.isEmpty()); // true

10. isPresent()

.isPresent()

정보

기능: Optional 객체가 있는지 확인.
리턴값: boolean

예제코드

// 인풋
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);

// 아웃풋
System.out.println(opt1.isPresent()); // true
System.out.println(opt2.isPresent()); // false

11. ifPresent()

.ifPresent(Consumer<? Super T> action)

정보

기능: Optional 객체가 있다면 내부 연산을 실행
리턴값: void

예제코드

// 인풋
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);

// 아웃풋
opt1.ifPresent(str -> System.out.println(str)); // Hello
opt2.ifPresent(str -> System.out.println(str)); 

.12. ifPresentOrElse()

ifPresentOrElse(Consumer<? Super T> action, Runnable emptyAction)

정보

기능: Optional 객체가 있다면 내부 연산을 실행, 없다면 또 다른 내부 연산을 실행
리턴값: void

예제코드

// 인풋
Optional<String> opt1 = Optional.ofNullable("Hello");
Optional<String> opt2 = Optional.ofNullable(null);

// 아웃풋
opt1.ifPresentOrElse(str -> System.out.println(str), 
						() -> System.out.println("null")); // Hello
opt2.ifPresentOrElse(str -> System.out.println(str), 
						() -> System.out.println("null")); // null

13. or()

.or(Supplier<? Extends Optional<? Extends T>> supplier)

정보

기능: Optional 객체가 비어있다면, 다른 Optional 객체를 반환.
리턴값: Optional<T>

예제코드

 // 인풋
Optional<String> optional1 = Optional.empty();
Optional<String> optional2 = Optional.of("Hello");

// Optional 메소드 사용
Optional<String> result1 = optional1.or(() -> Optional.of("World"));
Optional<String> result2 = optional2.or(() -> Optional.of("World"));

// 아웃풋
System.out.println(result1.get()); // World
System.out.println(result2.get()); // Hello

14. orElse()

.orElse(T other)

정보

기능: Optional 객체가 비어있다면, 전달된 기본값 other를 반환.
리턴값: T

예제코드

// 인풋
Optional<String> optional1 = Optional.empty();
Optional<String> optional2 = Optional.of("Hello");

// Optional 메소드 사용
String result1 = optional1.orElse(null);
String result2 = optional2.orElse(null);

// 아웃풋
System.out.println(result1); // null
System.out.println(result2); // Hello

15. orElseGet()

.orElseGet(Supplier<? Extends T> supplier)

정보

기능: Optional 객체가 비어있다면, 내부 함수를 실행하여 생성된 기본값을 반환.
리턴값: T

orElse()와 다른 점은 함수가 들어갈 수 있다는 점

예제코드

// 인풋
Optional<String> optional1 = Optional.empty();
Optional<String> optional2 = Optional.of("Hello");

// Optional 메소드 사용
String result1 = optional1.orElseGet(() -> null);
String result2 = optional2.orElseGet(() -> null);

// 아웃풋
System.out.println(result1); // null
System.out.println(result2); // Hello

16. orElseThrow()

.orElseThrow()
.orElseThrow(Supplier<? Extends X> exceptionSupplier)

정보

기능: Optional 객체가 비어있다면, Exception을 발생.
반환: T

예제코드

  • 파라미터 X
// 인풋
Optional<String> optional = Optional.empty();


// Optional 메소드 사용
String result = optional.orElseThrow(); // NoSuchElementException 발생
  • 파라미터 O
// 인풋
Optional<String> optional = Optional.empty();


// Optional 메소드 사용
String result = optional
					.orElseThrow(IllegalArgumentException::new); 
// IllegalArgumentException 발생

17. stream()

.stream()

정보

기능: Optional 객체의 값을 Stream으로 변환.
리턴값: Stream<T>

예제코드

// 인풋
Optional<String> optional = Optional.of("Hello");

// Optional 메소드 사용
optional.stream()
        .map(String::toUpperCase)
        .forEach(System.out::println); // HELLO

18. toString()

.toString()

정보

기능: Optional의 내부값을 String 문자열로 바꿔 반환.
리턴값: String

예제코드

// 인풋
Optional<String> optional = Optional.of("Hello");

// Optional 메소드 사용
String stringValue = optional.toString();

// 아웃풋
System.out.println(stringValue); // "Optional[Hello]"

19. hashCode()

.hashCode()

기능

기능: Optional 객체의 HashCode를 반환.
리턴값: int

예제코드

// 인풋
Optional<String> optional = Optional.of("Hello");
        
// Optional 메소드 사용
int hashCode = optional.hashCode();

// 아웃풋
System.out.println(hashCode); // 해시 코드
profile
학부생일뿐

0개의 댓글