2015-02-24 3 views
4

Не могли бы вы объяснить, почему проверенные исключения должны быть обнаружены из лямбда-выражений? Другими словами, почему следующий код не компилируется ...Проверенные исключения, выброшенные из лямбда-выражений

public void doSomething(ObjectInputStream istream) throws IOException { 
    // The read method throws an IOException. 
    IntStream.range(0, 10).forEach(i -> someList.add(read(istream))); 
} 

но этот один будет?

public void doSomething(ObjectInputStream istream) throws IOException { 
    IntStream.range(0, 10).forEach(i -> { 
    try { 
     // The read method throws an IOException. 
     someList.add(read(istream)); 
    } 
    catch (IOException ioe) { 
     // Callee has to handle checked exception, not caller. 
    } 
    }); 
} 

Похоже, вызываемая теперь должен обрабатывать любые проверяемые исключения, которые выбрасываются и не вызывающий.

ответ

8

Проблема не в выражении лямбда, это интерфейс, который он реализует. Помните, выражение лямбда в основном просто сокращает анонимный класс, который реализует данный интерфейс.

В этом случае forEach занимает java.util.function.Consumer<T>:

public interface Consumer<T> { 
    void accept(T t); 
    ... 
} 

Обратите внимание, что accept не объявлен, чтобы бросить что-нибудь. Это означает, что никакая реализация этого не может ничего бросить; не названный класс, а не анонимный класс, а не лямбда.

5

Кажется, что ваш метод read выбрасывает IOException.

Подпись IntStream.forEach: forEach(IntConsumer action), где IntConsumer имеет метод void accept(int value). В этом контексте ваше выражение лямбда i -> someList.add(read(istream)) эквивалентно:

public class IntConsumerImplementation implements IntConsumer { 
    ObjectInputStream istream; 
    public void accept(int i) { 
     someList.add(read(istream)); 
    }; 
} 

, который не компилируется, поскольку read бросает проверяемое исключение.

С другой стороны, лямбда-выражения могут бросок проверяемые исключения, если функциональный интерфейс определяет их (что не случай для потребителей или других java.util функциональных интерфейсов).

Пусть следующий составленный пример:

@FunctionalInterface 
public interface NotAnIntConsumer { 
    public void accept(int i) throws IOException; 
} 

Теперь следующий компилирует:

forEach(NotAnIntConsumer naic) { ... } 
doSomething(ObjectInputStream istream) throws IOException { 
    IntStream.range(0, 10).forEach(i -> someList.add(read(istream))); 
} 
Смежные вопросы