Повторное выбрасывание проверяемых исключений

Обновить

November 2018

Просмотры

6.3k раз

2
public void foo() {
 begin();
 try {
  ...
  commit();
 } catch (Exception e) {
  rollback();
  throw e;
 }
}

В приведенном выше примере, не существует ошибка , потому что fooне имеет throws Exception. Добавим , что не обойтись юзабилити метода ; много хорошего тоже.

Какой самый лучший способ сделать это? Как вы делаете что-то, если происходит ошибка, не действительно «обработки» ошибка?

9 ответы

0

Здесь вы случайно на одном из самых больших религиозных расколов в Java (если не шире), мир. Она сводится к тем, которые чувствуют, что TJ, кажется, и я тоже, что проверили исключения являются ценными по многим причинам, В.С. Род Джонсон / Весна школа, в разработке Java, проверяемые исключения были использованы во многих случаях, когда они не, скажем, закрытия или результирующий сокета, так потому, что он был неправильно использован во многих случаях, это делает их бесполезными, так что все исключения должны быть сняты. Есть много классов в рамках Spring, которые являются очень тонкими обертками вокруг стандартных объектов Java, но Превратить проверяемые исключения бесконтрольно. Это сводит меня с ума!

Во всяком случае, опусти меня так сильно, соглашаясь со всем, TJ сказал, но знаю, что вы, вероятно, никогда не найти «правильный» ответ.

1

Добавим, что не обойтись юзабилити метода; много хорошего тоже.

Нет . Это будет хорошо документации, а также вызывающий абонент будет заботиться обращением с ним.

Также см

6

По крайней мере , два подхода приходят на ум, которые, как правило , собираются быть объединены в зависимости от того, что вы хотите fooсделать:

1. Поймать и Rethrow только соответствующие исключения

Есть только так много исключений кода в главном потоке может бросить (вероятно , в основном , SqlExceptionс). Таким образом , только поймать и повторно выдать тех, и объявить , что вы делаете это. Более конкретно, повторно выдать только те , которые вы на самом деле не обработку (в вашем упрощенном примере кода, вы не справиться с любой, но ваш реальный код жизни, вероятно , более тонкий).

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

2. Не поймать исключение на всех

Как это:

// Signature changes to include any exceptions that really can be thrown
public void foo() throws XYZException, ABCException {
 // A flag indicating that the commit succeeded
 boolean done = false;

 begin();
 try {
  // Don't have any `return` statements in here (or if you do,
  // set `done` to `true` first)

  ...
  commit();
  done = true; // Commit didn't throw an exception, we're done
 } finally {
  // finally clause always happens regardless
  if (!done) {
    // We must be processing an exception; rollback
    try {
      rollback();
    } catch (Exception e) {
      // quash it (e.g., leave this block empty), we don't want
      // to mask the real exception by throwing a different one
    }
  }
 }
}

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

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

0

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

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

0

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

Просто ловить и протоколирование исключения не то, что я хотел бы рассмотреть обращение. Вместо Повторное выбрасывание, в этом случае я бы предпочел видеть проверенные исключения добавлены сигнатуры метода и пусть он пузыриться.

4

Поскольку Java 8 мы используем

/**
 * Cast a CheckedException as an unchecked one.
 *
 * @param throwable to cast
 * @param <T> the type of the Throwable
 * @return this method will never return a Throwable instance, it will just throw it.
 * @throws T the throwable as an unchecked throwable
 */
@SuppressWarnings("unchecked")
public static <T extends Throwable> RuntimeException rethrow(Throwable throwable) throws T {
    throw (T) throwable; // rely on vacuous cast
}

Вы можете повторно выдать проверяемое исключение, но только избегая компилятор проверяются проверки исключений.

public void foo() throws MyCheckedException {
 begin();
 try {
  ...
  commit();
 } catch (Exception e) {
  rollback();
  // same as throwing an exception without the compiler knowing.
  Thread.currentThread().stop(e); 
 }
}

Перед тем, как использовать стоп () вы должны прочитать http://download.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

. Thread.currentThread () остановка (е) .. поведенческий идентична операции броска Java, но обходят попытки компилятора, чтобы гарантировать, что вызывающий метод заявил все проверяемые исключения, что он может бросить:

0

Вы можете бросить подкласс RuntimeException - они не требуют задвижки ()

3

Оберните его с некоторыми RuntimeException, который бесконтрольно.

0

Стоит отметить некоторые достижения в этой области.

Во-первых, в Java 7, можно поймать и бросить общие исключения, до тех пор, как то, что объявленная внутри блока попробовать поймана или объявленная во внешнем блоке. Так что это будет составлять:

void test() throws SQLException {
  try { 
    conn.commit();
  } catch (Throwable t) {
    // do something
    throw t;
  }
}

Это хорошо описано здесь: http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html


Другой способ описан здесь: http://blog.jooq.org/2012/09/14/throw-checked-exceptions-like-runtime-exceptions-in-java/

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

try {
  do_operation
  flag_success
} catch (Throwable e) {
  flag_error
  throw e;
}

С использованием метода:

public static void wrapExec(RunnableT s) {
    try {
        s.run();
        flag_success
    } catch (Throwable t) {
        flag_error
        doThrow(t);
    }
}

и, следовательно, заменяя целый блок Try / поймать только с

wrapExec(()->{do_operation})