У меня есть сценарий, который обрабатывает миллионы данных. Те же данные повреждены, поэтому используемая мной структура дает сбой и выдает исключение. Я зависим от структуры, которую не могу изменить/обновить. Я использую его как есть. Каждый раз, когда я использую функцию этого фреймворка, я использую try/catch. Поэтому я использую много блоков try/catch, в результате код становится нечитаемым. Я хочу избавиться от блоков try/catch и обрабатывать исключения отдельно от моего кода.
Я хочу иметь глобальный обработчик исключений, поэтому всякий раз, когда платформа выдает исключение, оно должно перехватывать и регистрировать, а цикл обработки данных должен продолжаться. Существуют веб-фреймворки, такие как Spring и Jersey, которые имеют глобальный обработчик исключений. Я хочу аналогичного поведения для сценария.
Я попробовал Thread.UncaughtExceptionHandler, но по умолчанию UncaughtExceptionHandler останавливает процесс при возникновении исключения, поэтому он не срабатывает.
В настоящее время мой код выглядит так. Я хочу избавиться от блоков try/catch.
public static void main(String[] args) throws FrameworkException {
List<Element> elements = new ArrayList<>(); //Millons of data
processItems(elements)
}
public void processItems(List<Element> items) throws FrameworkException{
for (int i = 0; i < elements.size(); i++) {
try{
framework.doSomething(elements.get(i));
}
catch(FrameworkException e){
// handle
}
// . . .
try{
framework.doDifferentThing(elements.get(i));
}
catch(FrameworkException e){
// handle
}
// . . .
}
System.out.println("Processing completed.");
}
Код моей мечты и исключения обрабатываются глобально.
public void processItems(List<Element> items) throws FrameworkException{
for (int i = 0; i < elements.size(); i++) {
framework.doSomething(elements.get(i));
// . . .
framework.doDifferentThing(elements.get(i));
// . . .
}
System.out.println("Processing completed.");
}
Я использую множество блоков try/catch, в результате код становится нечитаемым. Я хочу избавиться от блоков try/catch и обрабатывать исключения отдельно от моего кода.
Если вы хотите перехватить и обработать исключение внутри цикла, то для этого вам нужно будет перехватить и обработать исключение внутри цикла. Если проблема в том, что в этом цикле слишком много блоков try/catch, то... Почему их так много? Чем они отличаются друг от друга? Пробовали ли вы их объединить? У вас уже есть работающий код, и вы просто ищете предложения по его рефакторингу и сокращению?
@KaanAteşel вы не можете «удалить всю отдельную обработку» И обрабатывать их все «отдельно». Но что мешает вам иметь один простой блок try-catch?
Если все, что вы делаете, это регистрируете исключение и продолжаете цикл, то почему бы просто не использовать одну попытку?
Мне приходится регистрировать разные объекты при каждой попытке. Я попробую объединить их еще раз, спасибо за ответы.
Обратите внимание, что у одного try
может быть несколько catch
.
Если framework.doSomething(elements.get(i));
выдает исключение, вы все равно хотите попробовать вызвать framework.doDifferentThing(elements.get(i));
на том же объекте? Или вы хотите прекратить обработку этого объекта в момент возникновения какого-либо исключения и перейти к следующему объекту?
Я хочу прекратить обработку элемента и перейти к следующему. Например, в веб-фреймворках, таких как Spring или Jersey, есть глобальный обработчик исключений, мне нужен аналогичный тип обработки исключений.
@KaanAteşel: «Глобальный» будет вне цикла. Если вы хотите обрабатывать исключения внутри цикла, вам следует сделать это внутри цикла. Похоже, вы просто неправильно понимаете, как работают исключения и стек вызовов в целом.
@Дэвид, спасибо за ответы, я проведу дополнительное исследование.
Похоже, вам просто нужен один блок try
-catch
внутри цикла, начиная со строки, следующей сразу за оператором for
(т. е. весь ваш цикл — это одна большая попытка).
Исключением является необычное поведение. Без него невозможно создать программу. Должен быть глобальный обработчик исключений для перехвата всех непроверенных исключений, если вы не запрограммировали выход. В противном случае избегать каких-либо исключений плохо, особенно если оно отмечено.
Вам нужно объяснить более подробно: «Мне нужно регистрировать разные объекты при каждой попытке».
Вы можете определить функциональный интерфейс для представления действий, выполняемых над любым Element
, который может вызвать FrameworkException
. Затем вам просто нужно реализовать метод, который принимает как действие, так и текущий элемент. Этот метод инкапсулирует логику try-catch и применяет действие к элементу.
@FunctionalInterface
public interface ElementAction {
void execute(Element element) throws FrameworkException;
}
public void tryAction(ElementAction action, Element element) {
try {
action.execute(element);
} catch (FrameworkException e) {
// do whatever you usually do for exceptions
}
}
Таким образом, вы можете сделать свой processItems
чище следующим образом:
public void processItems(List<Element> items) {
for (Element item : items) {
tryAction(element -> framework.doSomething(item), item);
// . . .
tryAction(element -> framework.doDifferentThing(item), item);
// . . .
}
// cont.
}
редактировать (просто прочитайте комментарии к основному сообщению):
Вы можете расширить метод tryAction
, передав BiConsumer
, который принимает Element
и FrameworkException
для пользовательского входа в систему.
@FunctionalInterface
public interface ExceptionLogger extends BiConsumer<Element, FrameworkException> {}
Затем вы добавите его в метод tryAction
:
public void tryAction(ElementAction action, Element element, ExceptionLogger logger) {
try {
action.execute(element);
} catch (FrameworkException e) {
logger.accept(element, e);
}
}
Затем в свой processItems
вы должны добавить свой способ регистрации исключения:
public void processItems(List<Element> items) {
for (Element item : items) {
tryAction((
element -> framework.doSomething(item),
item,
(element, e) -> System.err.println("this error " + e.getMessage())
);
// . . .
tryAction(
element -> framework.doDifferentThing(item),
item,
(element, e) -> System.err.println("that error " + e.getMessage())
);
// . . .
}
// cont.
}
(при условии, что вы используете Java 8+, что вам действительно нужно в наши дни)
Похоже, вы хотите, чтобы цикл продолжался всякий раз, когда возникает исключение платформы:
for (Element item : items) {
try {
framework.doSomething(item);
// ...
framework.doDifferentThing(item);
} catch (FrameworkException | SomeOtherFrameworkException e) {
logger.log(Level.INFO, "Corrupted element " + item, e);
}
}
Это позволяет вашей логике выглядеть непрерывной, без визуального разделения на несколько блоков catch
.
Вам не следует использовать какую-то магическую аннотацию, чтобы скрыть блоки try/catch от других разработчиков. Распространение вашей логики на другие места без какой-либо ссылки на них только значительно затруднит дальнейшее обслуживание.
Однако в данном случае я не думаю, что будет какой-либо способ сделать это, несмотря ни на что. Вам необходимо перехватить исключение, если вы хотите восстановиться после него и продолжить цикл.
«он должен перехватывать и регистрировать, и цикл обработки данных должен продолжаться». Тогда это звучит так, будто вы хотите перехватить и обработать исключение внутри цикла. Что вы, судя по всему, уже делаете. Можете ли вы уточнить, почему ваша попытка не работает должным образом?