Создать безопасную оболочку выполнения исключений в Java

У меня много кода с try / catch, и почти во всех случаях я предпринимаю одно и то же действие. Я хочу упростить обработку ошибок, создав что-то, где я могу просто сказать

ManagedExceptionEnvironment() {
    // The code that might throw exceptions
}

А внутри ManagedExceptionEnvironment есть общая логика обработки ошибок.

Моя первоначальная мысль об этом заключалась в том, чтобы конструктор ManagedExceptionEnvironment взял Runnable, но если вы поместите логику, которая может вызвать исключение внутри анонимного метода Runnablerun, тогда он все равно будет жаловаться на то, что не реализует try / catch, даже если контейнер, в который вы его передаете. позаботился бы об этом.

Я полагаю, что другой вариант - обрабатывать ошибки только на самом высоком уровне и заставлять их продолжать подниматься на другой уровень, хотя это кажется довольно рискованным.

Обновлено: я думаю, что один из вариантов здесь (и я не знаю, есть ли это в Java) - это какой-то макрос?

Изменить 2: только что бегло прочитал об использовании препроцессора C для вставки макросов в Java src, и это действительно ужасно. Так что макросы - это не решение.

Лямбда-выражения доступны для каждая версия Android.

CommonsWare 18.08.2018 19:23

@CommonsWare, значит, все версии Android поддерживают лямбды, но не все другие функции Java 8?

Nick Chapman 18.08.2018 19:28

Это неоднозначная картина. Важно то, что Java 8 классы недоступна до уровня API 24. Лямбда-выражения не включают классы Java 8. Цепочка инструментов Android генерирует скомпилированный код для лямбда-выражений, которые могут работать на любой версии Android.

CommonsWare 18.08.2018 19:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
1 044
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как насчет того, чтобы обернуть его таким интерфейсом:

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>)

Другие вопросы по теме