( Позднее редактирование: Этот вопрос, надеюсь, будет устаревшим, когда появится Java 7 из-за "final rethrow" feature, который кажется, что он будет добавлен.)
Довольно часто я нахожусь в ситуациях, выглядящих так:
do some initialization try { do some work } catch any exception { undo initialization rethrow exception }
В С# вы можете сделать это следующим образом:
InitializeStuff();
try
{
DoSomeWork();
}
catch
{
UndoInitialize();
throw;
}
Для Java нет хорошей подстановки, и поскольку предложение об улучшенной обработке исключений было отключено от Java 7, похоже, Я возьму в лучшем случае несколько лет, пока мы не получим что-то вроде этого. Таким образом, я решил бросить свое:
( Изменить: Полгода спустя окончательный ретрон вернулся, или так кажется.)
public final class Rethrow {
private Rethrow() { throw new AssertionError("uninstantiable"); }
/** Rethrows t if it is an unchecked exception. */
public static void unchecked(Throwable t) {
if (t instanceof Error)
throw (Error) t;
if (t instanceof RuntimeException)
throw (RuntimeException) t;
}
/** Rethrows t if it is an unchecked exception or an instance of E. */
public static <E extends Exception> void instanceOrUnchecked(
Class<E> exceptionClass, Throwable t) throws E, Error,
RuntimeException {
Rethrow.unchecked(t);
if (exceptionClass.isInstance(t))
throw exceptionClass.cast(t);
}
}
Типичное использование:
public void doStuff() throws SomeException {
initializeStuff();
try {
doSomeWork();
} catch (Throwable t) {
undoInitialize();
Rethrow.instanceOrUnchecked(SomeException.class, t);
// We shouldn't get past the above line as only unchecked or
// SomeException exceptions are thrown in the try block, but
// we don't want to risk swallowing an error, so:
throw new SomeException("Unexpected exception", t);
}
private void doSomeWork() throws SomeException { ... }
}
Это немного словесный, ловкий Throwable
, как правило, нахмурился, я не очень-то счастлив в использовании рефлексии только для того, чтобы реконструировать исключение, и я всегда чувствую немного неловкое письмо "это не произойдет", но в практика работает хорошо (или, по крайней мере, кажется). Я задаюсь вопросом:
- Есть ли у меня какие-то недостатки в методах повторного броузера? Некоторые угловые случаи, которые я пропустил? (Я знаю, что
Throwable
может быть вызвано чем-то настолько серьезным, что мойundoInitialize
не удастся, но это ОК.)- Кто-то уже придумал это? Я смотрел Commons Lang
ExceptionUtils
, но это делает другие вещи.
- Кто-то уже придумал это? Я смотрел Commons Lang
Edit:
-
finally
не тот дроид, которого я ищу. Мне просто интересно делать что-то, когда вызывается исключение. - Да, я знаю, что ловить
Throwable
большое нет-нет, но я думаю, что это меньшее зло здесь по сравнению с тремя предложениями catch (дляError
,RuntimeException
иSomeException
соответственно) с одинаковыми код. - Обратите внимание, что я не пытаюсь подавить какие-либо ошибки - идея состоит в том, что любые исключения, которые были выбраны в блоке
try
, будут продолжать пузыриться через стек вызовов, как только я перемотал несколько вещей.