В Java 8 появились такие полезные функции, как лямбда-выражения и потоки, которые значительно упрощают написание кода и делают его более читаемым. Однако, при использовании этих новых функций, могут возникнуть сложности, связанные с обработкой исключений, особенно проверяемых исключений.
Представим типичную ситуацию. Например, необходимо преобразовать список названий классов в список объектов Class
с помощью потока и функции Class.forName()
. Эта функция может бросить ClassNotFoundException
, который является проверяемым исключением.
public List<Class> getClasses() throws ClassNotFoundException { List<Class> classes = Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") .map(className -> Class.forName(className)) .collect(Collectors.toList()); return classes; }
В этом случае код не скомпилируется, потому что лямбда-выражения и потоки не позволяют бросать проверяемые исключения без обработки их внутри блока try
/catch
.
Однако, оборачивание проверяемого исключения внутрь непроверяемого исключения или добавление блока try
/catch
внутри потока может сделать код менее читаемым и красивым.
Один из способов обойти это ограничение — использование кастомного функционального интерфейса, который может бросать проверяемые исключения. Например:
@FunctionalInterface public interface ThrowingFunction<T, R, E extends Exception> { R apply(T t) throws E; }
Теперь можно использовать этот интерфейс вместе с потоком и лямбда-выражением:
public List<Class> getClasses() throws ClassNotFoundException { ThrowingFunction<String, Class, ClassNotFoundException> mapFunction = className -> Class.forName(className); List<Class> classes = Stream.of("java.lang.Object", "java.lang.Integer", "java.lang.String") .map(mapFunction) .collect(Collectors.toList()); return classes; }
Такой подход позволяет избежать необходимости оборачивать проверяемые исключения внутрь непроверяемых исключений или добавлять блоки try
/catch
внутри потока, сохраняя код чистым и читаемым.
Добавить комментарий