Может ли лямбда-выражение в Java бросать проверяемые исключения (checked exceptions)?

«Может ли лямбда-выражение в Java бросать проверяемые исключения (checked exceptions)?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, не может напрямую. Лямбда-выражение должно соответствовать абстрактному методу своего функционального интерфейса (например, apply в Function<T, R>). Если этот метод не объявляет проверяемые исключения в throws, то и лямбда не может их бросать.

Почему это ограничение? Для сохранения совместимости с системой типов Java и существующими функциональными интерфейсами из java.util.function.

Обходные пути:

  1. Обернуть исключение в RuntimeException: Самый распространенный способ.
    Function<String, Integer> parser = s -> {
        try {
            return Integer.parseInt(s);
        } catch (NumberFormatException e) { // NumberFormatException - unchecked
            // А если бы исключение было checked, мы бы обернули его:
            // throw new RuntimeException(e);
            throw e;
        }
    };
  2. Использовать собственный функциональный интерфейс, который объявляет исключение.

    @FunctionalInterface
    interface CheckedFunction<T, R> {
        R apply(T t) throws Exception; // Объявляем Exception
    }
    
    CheckedFunction<String, Integer> riskyParser = s -> Integer.parseInt(s); // Теперь можно
  3. Написать вспомогательный метод-обертку, который преобразует исключения.

Вывод: Лямбды работают в рамках контракта интерфейса. Для обработки checked exceptions требуется дополнительная обработка.