orElseThrow

optional 클래스의 orElseThrow

Optional 클래스의 orElseThrow

orElseThrowOptional 클래스의 메서드로, 값이 존재하면 그 값을 반환하고, 값이 존재하지 않으면 예외를 던지도록 설계되었습니다. 이 메서드는 Supplier 인터페이스를 통해 예외를 생성하는데, Supplier는 인자를 받지 않고 결과를 반환하는 함수형 인터페이스입니다.

 

orElseThrow 메서드는 다음과 같이 정의되어 있습니다

 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
      if (value != null) {
          return value;
      } else {
          throw exceptionSupplier.get();
      }
  }

이 메서드는 값이 존재하면 그 값을 반환하고, 값이 없으면 Supplier를 통해 예외를 생성하여 던집니다. Supplier@FunctionalInterface 어노테이션이 붙은 인터페이스로, 단 하나의 추상 메서드 get을 가지고 있습니다

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

`

orElseThrow 메서드를 사용할 때는 보통 람다 표현식을 사용하여 예외 객체를 생성합니다. 예를 들어, find 메서드에서 특정 ID에 해당하는 Knowledge 객체를 찾지 못했을 때 예외를 던지도록 다음과 같이 작성할 수 있습니다:

public Knowledge find(Long knowledgeId) {
		return knowledgeRepository.findById(knowledgeId).orElseThrow(() -> new CustomRuntimeException(
			KnowledgeException.KNOWLEDGE_NOT_FOUND));
	}

이 코드는 knowledgeId에 해당하는 Knowledge 객체가 존재하지 않으면 CustomRuntimeException을 던집니다. 여기서 사용된 람다 표현식 () -> new CustomRuntimeException(KnowledgeException.KNOWLEDGE_NOT_FOUND)Supplier<CustomRuntimeException> 타입의 인스턴스를 생성합니다. (CustomRuntimeException 구조)

 

최종적으로 위와같이

public Knowledge find(Long knowledgeId) {
		return knowledgeRepository.findById(knowledgeId).orElseThrow(() -> new CustomRuntimeException(
			KnowledgeException.KNOWLEDGE_NOT_FOUND));
	}

예외가 던져진다하면 orElseThrow 안에 제네릭은 타입 추론에 의하여

public <CustomRuntimeException extends Throwable> T orElseThrow(Supplier<? extends CustomRuntimeException> exceptionSupplier) throws CustomRuntimeException {
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

이렇게 바뀌고 value 즉 위에선 Knowledge 가 없는경우 CustomRuntimeExceptionthrow 되게 됩니다.

그후 ControllerAdvice 등의 예외 처리 로직에 의하여 예외가 처리 됩니다.

+ Recent posts