1. 소개

JDK에서 제공 하는 기능적 인터페이스 는 확인된 예외 처리를 위해 적절하게 준비되지 않았습니다. 문제에 대해 자세히 알아보려면 이 문서를 확인하십시오.

이 기사에서는 기능적인 Java 라이브러리 Vavr 을 사용하여 이러한 문제를 극복하는 다양한 방법을 살펴보겠습니다 .

Vavr 및 설정 방법에 대한 자세한 내용은 이 문서 를 확인하세요 .

2. CheckedFunction 사용하기

Vavr은 확인된 예외를 발생시키는 기능이 있는 기능적 인터페이스 를 제공합니다. 이러한 기능은 CheckedFunction0 , CheckedFunction1 등 CheckedFunction8 까지 입니다 . 함수 이름 끝에 있는 0 , 1, … 8 은 함수의 입력 인수 수를 나타냅니다.

예를 보자:

static Integer readFromFile(Integer integer) throws IOException {
    // logic to read from file which throws IOException
}

IOException 을 처리하지 않고 람다 식 내에서 위의 메서드를 사용할 수 있습니다 .

List<Integer> integers = Arrays.asList(3, 9, 7, 0, 10, 20);

CheckedFunction1<Integer, Integer> readFunction = i -> readFromFile(i);
integers.stream()
 .map(readFunction.unchecked());

보시다시피 표준 try-catch 또는 래퍼 메서드 없이도 람다 식 내에서 예외를 던지는 메서드를 호출할 수 있습니다.

Stream API 와 함께 이 기능을 사용하는 동안 주의를 기울여야 합니다 . 예외가 발생하면 작업이 즉시 종료되어 스트림의 나머지 부분이 버려집니다.

3. 도우미 메서드 사용

API 클래스는 이전 섹션의 예에 대한 바로 가기 메서드를 제공합니다.

List<Integer> integers = Arrays.asList(3, 9, 7, 0, 10, 20);

integers.stream()
  .map(API.unchecked(i -> readFromFile(i)));

4. 리프팅 사용

IOException 을 정상적으로 처리하기 위해 람다 식 내부에 표준 try-catch 블록을 도입할 수 있습니다. 그러나 람다 식의 간결성은 손실됩니다. Vavr의 리프팅이 우리를 구해줍니다.

리프팅은 함수형 프로그래밍의 개념입니다. 결과로 Option 을 반환하는 전체 함수로 부분 함수를 들어 올릴 수 있습니다 .

부분 함수는 도메인 전체에 대해 정의되는 전체 함수와 달리 도메인의 하위 집합에 대해서만 정의되는 함수입니다. 부분 함수가 지원 범위를 벗어난 입력으로 호출되면 일반적으로 예외가 발생합니다.

이전 섹션의 예를 다시 작성해 보겠습니다.

List<Integer> integers = Arrays.asList(3, 9, 7, 0, 10, 20);
 
integers.stream()
  .map(CheckedFunction1.lift(i -> readFromFile(i)))
  .map(k -> k.getOrElse(-1));

리프트된 함수의 결과는 Option 이며 예외의 경우 결과는 Option.None 이 됩니다. getOrElse() 메서드 는 Option.None 의 경우 반환할 대체 값을 사용 합니다.

5. 사용해보기

이전 섹션의 lift() 메서드 는 갑작스러운 프로그램 종료 문제를 해결하지만 실제로는 예외를 삼켜 버립니다. 결과적으로 우리 방법의 소비자는 기본값이 무엇인지 알 수 없습니다. 대안은 Try 컨테이너를 사용하는 것입니다.

Try 는 예외를 throw할 수 있는 작업을 포함할 수 있는 특수 컨테이너입니다. 이 경우 결과 Try 개체는 실패 를 나타내며 예외를 래핑합니다.

Try 를 사용하는 코드를 살펴보겠습니다 .

List<Integer> integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.stream()
  .map(CheckedFunction1.liftTry(i -> readFromFile(i)))
  .flatMap(Value::toJavaStream)
  .forEach(i -> processValidValue(i));

Try 컨테이너 및 사용 방법 에 대한 자세한 내용은 이 문서 를 확인하십시오 .

6. 결론

이 빠른 기사에서는 Vavr 라이브러리의 기능을 사용하여 람다 식의 예외를 처리하면서 문제를 피하는 방법을 보여주었습니다.

이러한 기능을 통해 예외를 우아하게 처리할 수 있지만 최대한 주의해서 사용해야 합니다. 이러한 접근 방식 중 일부에서는 메서드 소비자가 명시적으로 선언되지는 않았지만 예기치 않은 확인된 예외로 인해 놀랄 수 있습니다.

이 기사의 모든 예제에 대한 전체 소스 코드는 Github 에서 찾을 수 있습니다 .

Generic footer banner