Java/함수형 인터페이스

[Java]람다 표현식에서 Unchecked Exception 처리

DevStory 2022. 11. 3.

람다 표현식 Unchecked Exception 처리

Java 8에 도입된 람다 표현식(Lambda expression)은 이름이 없는 익명 함수로 메서드의 동작을 간결하게 작성할 수 있습니다. 그러나, JDK에서 제공하는 함수형 인터페이스는 예외(Exception)를 다루는 경우가 거의 없습니다.

 

따라서, 개발자가 람다 표현식에서 발생하는 예외를 방지하기 위해 예외를 처리하는 코드를 구현해야 합니다. 람다 표현식 예외를 처리하는 코드를 구현하면 한 가지 문제가 발생하는데, 람다 표현식 사용 목적과 다르게 간결했던 코드가 장황하고 복잡해집니다.

 

이번 포스팅은 람다 표현식에서 예외가 발생하는 경우와 예외를 올바르게 처리하는 방법을 소개합니다.


문제가 발생하는 코드

먼저 람다 표현식에서 예외가 발생하는 경우를 살펴봅시다.

 

다음 예제는 정수 100을 List<Integer>의 요소로 나눈 결과를 출력합니다.

public static void main(String args[]) {
  List<Integer> intList =
          new ArrayList<>(Arrays.asList(10, 5, 0, 20, 25));

  System.out.print("출력: ");
  intList.forEach(num -> System.out.print((100 / num) + " "));
}

[에러 내용]

위 예제는 한 가지 문제가 존재합니다. 100을 0으로 나누는 경우 ArithmeticException / by zero 예외가 발생합니다. 0으로 나누었을 때, 발생하는 예외를 방지하기 위해 try-catch문을 추가합니다.

 

다음 예제는 try-catch문이 추가된 코드입니다.

public static void main(String args[]) {
  List<Integer> intList =
          new ArrayList<>(Arrays.asList(10, 5, 0, 20, 25));

  System.out.print("출력: ");
  intList.forEach(num -> {
    try {
      System.out.print((100 / num) + " ");
    } catch (ArithmeticException ex) {
      System.out.println("\n100은 0으로 나눌 수 없습니다.");
    }
  });
}

[실행 결과]

출력: 10 20 
100은 0으로 나눌 수 없습니다.
5 4

try-catch문을 사용하여 예외를 처리하였지만 간단한 코드가 복잡해졌으며, 간결함도 사라졌습니다. 이 문제를 해결하기 위해 람다 래퍼를 구현합니다.


람다 래퍼를 구현

forEach() 메서드 내부에 작성된 코드를 래퍼 메서드로 처리합니다.

public class Program {
  // 람다 래퍼(Lambda Wrapper)
  static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
    return num -> {
      try {
        consumer.accept(num);
      } catch (Exception ex) {
        System.out.println("\n" + ex.getClass() + ex.getMessage());
      }
    };
  }

  public static void main(String args[]) {
    List<Integer> intList =
            new ArrayList<>(Arrays.asList(10, 5, 0, 20, 25));

    System.out.print("출력: ");
    intList.forEach(lambdaWrapper(num -> System.out.print((100 / num) + " ")));
  }
}

[실행 결과]

출력: 10 20 
class java.lang.ArithmeticException/ by zero
5 4

try-catch문이 추가된 로직을 래퍼 함수로 옮겼기에 forEach() 메서드 내부의 코드는 간결해졌지만 코드의 줄 수는 큰 변화가 없습니다.

 

하지만, 람다 래퍼를 여러 번 호출할 수 있으므로 코드 재사용은 높아지므로 코드를 작성하는 시간은 감소하고 가독성은 향상됩니다.

public class Program {
  // 람다 래퍼(Lambda Wrapper)
  static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
    return num -> {
      try {
        consumer.accept(num);
      } catch (Exception ex) {
        System.out.println("\n" + ex.getClass() + ex.getMessage());
      }
    };
  }

  public static void main(String args[]) {
    List<Integer> intList =
            new ArrayList<>(Arrays.asList(10, 5, 0, 20, 25));

    System.out.print("출력: ");
    intList.forEach(lambdaWrapper(num -> System.out.print((100 / num) + " ")));
    
    System.out.print("출력: ");
    intList.forEach(lambdaWrapper(num -> System.out.print((50 / num) + " ")));

    System.out.print("출력: ");
    intList.forEach(lambdaWrapper(num -> System.out.print((25 / num) + " ")));
  }
}
반응형

댓글