2013-12-20 5 views
2

Я в тяжелой ситуации, которая суммируется по следующему коду.Работа с несколькими исключениями

try { 
    dangerousCode(); // Declares `throws ExecutionException` 
} 
catch (ExecutionException ex) { 
    handleIt(); 
    throw ex; 
} 
catch (RuntimeException ex) { 
    handleIt(); 
    throw new ExecutionException(ex); 
} 
finally { 
    notifyListeners(); // May throw RuntimeException! 
} 

Я хотел бы придерживаться договоров распространяющегося потенциального ExecutionException производного от опасного кода - явно брошенного, или Обертывания RuntimeException.

Однако слушатели в finally блоке (которые я не контролирую) могут бросить другое выполнения исключения. Конечно, я также хотел бы уведомить клиента об этом событии.

Дилемма: У меня теперь есть два исключения на руках.

Я мог бы определить свой собственный тип исключения для обертывания обоих исключенных исключений.

class MyExecutionException { 
    Throwable getCause(); 
    Throwable getSecondCause(); 
} 

Мне просто интересно, есть ли другой способ решения этой проблемы?

+1

Поскольку Java 7 вы можете использовать: '} поймать (ExecutionException | RuntimeException ех) {' – Sergi

+0

@Sergi Я знаю , но тогда я буду обертывать «ExecutionException» с помощью другого «ExecutionException». В этом разница между обоими блоками catch. – afsantos

+0

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

ответ

1

Мне просто интересно, есть ли другой способ решения этой проблемы?

Ваша идея прекрасна. Использование собственных классов для try-catch, вложенных в catch или finally, является обычной практикой. В больших приложениях такие конструкции почти неизбежны.

Ваш класс может выглядеть следующим образом:

class MyExecutionException extends MyLogicException { 
    //what happened in the first place 
    Throwable getOriginException(); 

    // what have we tried? 
    Throwable getRecoveryException(); 

    // more than 1 thing can happen in recovery, order is important, hence list 
    List<Throwable> getAllExceptions(); 
} 

Такой подход позволяет иметь всю информацию в одном месте и делает реализацию одного места для обработки исключений и протоколирование очень легко. Просто убедитесь, что вы делаете свой класс обертки/контейнера исключений настолько универсальным, насколько это возможно в соответствии с вашими будущими потребностями.

+0

Я не знал, что это обычная практика. Спасибо, что поняли это. – afsantos

0

Вы можете использовать два метода initCause() и getCause(), которые могут обернуть исключение:

Exception e = new Exception(); 
e.initCause(new Exception()); 
Throwable t = e.getCause(); //returns Throwable 
+1

Проблема заключается в том, что в этом подходе никогда не будет двух (и более) отдельных «ветвей» исключений - что должно быть в случае исключения, возникающего при попытке восстановления из другого исключения. – Dariusz