Programing Language/Java

Optional

jheaon 2024. 5. 24. 16:53

 

오늘은 Optional에 대해서 알아보자

 


목차
1.Optional
2.사용방법

Optional

Java8에서 나온 문법으로 NullPointerException(NPE)을 방지하도록 도와주는 클래스이다. Optional <T>을 이용하여 사용할 수 있으며 null이 올 수 있는 값을 감싸는 Wrapper 클래스로 나타낸다. 아래 코드와 같이 값을 저장하기 때문에, 참조하더라도 NPE가 발생하지 않도록 도와준다.

public final class Optional<T> {

  // If non-null, the value; if null, indicates no value is present
  private final T value;
   
  ...
}

 

 

사용방법

  • Optional.empty() : 값이 null인 경우

Optional은 Wrapper 클래스이기 때문에 값이 없을 수도 있는데, 이때 Optional.empty()로 생성할 수 있다.

Optional<String> optional = Optional.empty();

System.out.println(optional); // Optional.empty
System.out.println(optional.isPresent()); // false

 

 

 

  • Optional.of() : 값이 null이 아닐 경우

만약 어떤 데이터가 절대 null이 아니라면, Optional.of()을 통해 값을 가져올 수 있다. 만약 Optional.of()에 null을 저장하려고 하면 NullPointerException이 발생한다. 

Optional<String> optional = Optional.of("MyName");

 

 

 

  • Optional.ofNullable() : 값이 null일수도, 아닐 수도 있는 경우

만약 어떤 데이터가 null 혹은 데이터가 올 경우에는 Optional.ofNullable로 생성이 가능하다. 이후 orElse, orElseGet 메서드를 이용하여 값을 가져올 수 있다. 

// Optional의 value는 값이 있을 수도 있고 null 일 수도 있다.
Optional<String> optional = Optional.ofNullable(getName());
String name = optional.orElse("anonymous"); // 값이 없다면 "anonymous" 를 리턴

 

orElse와 orElseGet 차이

  • orElse : 파라미터로 값을 받는다.
  • orElseGet: 파라미터로 함수형 인터페이스(함수)를 받는다.

해당 메서드를 이렇게 구별한 이유는 작동방식 때문인데 그 예시로 아래 코드를 살펴보자.

public void findUserEmailOrElse() {
    String userEmail = "Empty";
    String result = Optional.ofNullable(userEmail)
    	.orElse(getUserEmail());
        
    System.out.println(result);
}

public void findUserEmailOrElseGet() {
    String userEmail = "Empty";
    String result = Optional.ofNullable(userEmail)
    	.orElseGet(this::getUserEmail);
        
    System.out.println(result);
}

private String getUserEmail() {
    System.out.println("getUserEmail() Called");
    return "JHeaon@tistory.com";
}

=================================================

// orElse인 경우
getUserEmail() Called
Empty

// orElseGet인 경우
Empty

 

OrElse인 경우 아래와 같이 동작한다. 

  1. Optional.ofNullable로 Optional 객체 생성
  2. getUserEmail()이 실행되어 반환값을 orElse 파라미터로 전달
  3. orElse가 호출되어 "EMPTY"가 Null이 아니므로 "EMPTY"을 가짐

하지만 이 경우에 getUserEmail() 함수가 무조건 실행이 되는데 이는 추후 큰 문제를 불러일으킬 수 있다. 예를 들어서 유저 이메일을 등록하는 코드를 작성했다고 가정한다. 이때 userEmail은 Unique 한 값으로 작성되었다고 가정한다. 

public void findByUserEmail(String userEmail) {
    // orElse에 의해 userEmail이 이미 존재해도 유저 생성 함수가 호출되어 에러 발생
    return userRepository.findByUserEmail(userEmail)
            .orElse(createUserWithEmail(userEmail));
}

private String createUserWithEmail(String userEmail) {
    User newUser = new User(userEmail);
    return userRepository.save(newUser);
}

 

이 경우 조회결과에 무관하게 createUserWithEmail() 함수가 반드시 실행되게 된다. 하지만 DB에서 userEamil은 Unique로 설정되어 있기 때문에 해당 코드를 실행 시 오류가 난다.

 

따라서 이러한 문제를 해결하기 위해 나온 함수가 orElseGet()이다. orElseGet()은 파라미터로 함수 자체를 전달받아 함수가 반드시 실행되는 것을 막아준다.

 

 

 

 

  • Optional.orElseThrow() : 값이 null 일 때, 예외를 던지고 싶을 경우
Optional<String> nameOpt = Optional.ofNullable(getName());
String result = nameOpt.orElseThrow(CustomUpperCaseExcpetion::new)
                  .toUpperCase();

 

 

'Programing Language > Java' 카테고리의 다른 글

Lambda Expression  (0) 2024.06.05
Enum  (0) 2024.05.31
Stream  (0) 2024.05.09
Thread (수정중)  (1) 2024.05.01
String 객체  (0) 2024.04.30

'Programing Language/Java'의 다른글

  • 현재글 Optional

관련글