У меня много кода с try / catch, и почти во всех случаях я предпринимаю одно и то же действие. Я хочу упростить обработку ошибок, создав что-то, где я могу просто сказать
ManagedExceptionEnvironment() {
// The code that might throw exceptions
}
А внутри ManagedExceptionEnvironment есть общая логика обработки ошибок.
Моя первоначальная мысль об этом заключалась в том, чтобы конструктор ManagedExceptionEnvironment взял Runnable, но если вы поместите логику, которая может вызвать исключение внутри анонимного метода Runnablerun, тогда он все равно будет жаловаться на то, что не реализует try / catch, даже если контейнер, в который вы его передаете. позаботился бы об этом.
Я полагаю, что другой вариант - обрабатывать ошибки только на самом высоком уровне и заставлять их продолжать подниматься на другой уровень, хотя это кажется довольно рискованным.
Обновлено: я думаю, что один из вариантов здесь (и я не знаю, есть ли это в Java) - это какой-то макрос?
Изменить 2: только что бегло прочитал об использовании препроцессора C для вставки макросов в Java src, и это действительно ужасно. Так что макросы - это не решение.
@CommonsWare, значит, все версии Android поддерживают лямбды, но не все другие функции Java 8?
Это неоднозначная картина. Важно то, что Java 8 классы недоступна до уровня API 24. Лямбда-выражения не включают классы Java 8. Цепочка инструментов Android генерирует скомпилированный код для лямбда-выражений, которые могут работать на любой версии Android.




Как насчет того, чтобы обернуть его таким интерфейсом:
class ManagedExceptionEnvironment {
public static void safeExecution(Wrapper w) {
try {
w.codeThatThrows();
} catch (Exception e) {
// your error handling
}
}
public static void example() {
safeExecution(() -> { throw new Exception(); });
// Or the old-fashioned way:
safeExecution(new Wrapper() {
@Override
public void codeThatThrows() throws Exception {
throw new Exception();
}
});
}
interface Wrapper {
public void codeThatThrows() throws Exception;
}
}
Хитрость в том, что метод, аналогичный Runnable.run(), указывает, что он может генерировать исключение, тогда как run() этого не делает.
Вы можете сделать исключения частью (общей) сигнатуры вашего интерфейса / класса / метода. См. Мой вопрос (Как не генерировать общее исключение?) в качестве примера.
Вместо вызова метода «newInstance ()» вы можете назвать его, например, «process ()». А затем создайте вокруг этого типобезопасный обработчик. А клиенты просто передают лямбда-выражения.
В основном определение вашей собственной оболочки (как показано в другом ответе :-)
Если ManagedExceptionEnvironment не собирался расширять какой-либо существующий класс, здесь нет смысла использовать класс Java в отличие от метода static. Итак, вы могли написать:
public static <T> T boomProtector(Callable<T> thingThatMightGoBoom) {
try {
return thingThatMightGoBoom.call();
}
catch(Exception e) {
// TODO: your standard catch logic
}
return null;
}
Затем, где вам это нужно, вы можете вызвать:
Whatever result = boomProtector(() -> earthShatteringKaboom());
где Whatever - это тип, возвращаемый earthShatteringKaboom(). Если earthShatteringKaboom() возвращает объект, вы получаете его в result. Если это вызывает исключение, выполняется ваша стандартная логика перехвата и result - это null.
(примечание: я показываю синтаксис Java 8 для примера вызова boomProtector(), который вам нужно будет включить в своем проекте, например, через File> Project Settings> app в Android Studio - или используйте реализацию анонимного внутреннего класса Callable<T>)
Лямбда-выражения доступны для каждая версия Android.