Ответ 1
В общем, метод Throwable addSuppressed()
должен использоваться, когда каким-то образом мы выполняем параллельное выполнение, которое может создавать исключение, которое подавляется. Я нашел 2 примера;
-
Блок try-with-resource (блок try-finally), когда вызывающий код увидит исходное исключение (в блоке try или catch) и исключение, которое произошло в блоке finally.
-
пакетные задания (массовые операции), когда мы должны перейти к следующему элементу независимо от того, выполнена ли операция над текущим элементом или нет
Прежде чем перейти к деталям, как указано в @sarelbotha, в моем случае мне просто нужно продолжать обматывать исходное исключение как причину моего нового исключения.
Поведение по умолчанию в блоке try-finally, где у нас есть 2 исключения, что исходное исключение подавлено, и мы видим только исключение из блока finally. Если мы используем окончательный блок для того, чтобы закрыть ресурс, чем мы действительно хотим видеть исходное исключение, но, возможно, мы также хотим увидеть также исключения из блока finally, которые закрыли наш ресурс и не удались.
Начиная с версии 7, платформа поддерживает понятие исключенных исключений (в сочетании с оператором try-with-resources). Любые исключения, которые были подавлены для предоставления исключения, распечатываются под трассировкой стека.
http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#printStackTrace%28%29
Сначала нужно прочитать о новой функции try-with-resource. Здесь вы можете прочитать здесь http://www.baptiste-wicht.com/2010/08/java-7-try-with-resources-statement/ или здесь Что такое Java 7 try-with -ресурсы эквивалент байт-кода с помощью try-catch-finally?. Короче говоря, вы можете иметь 2 Throwable параллельно в каком-то смысле, как правило, от вас, попробуйте блок и ваш блок finally. Старая семантика try-catch вернет исключение из блока finally whull suppressed исключение из блока try (или реорганизация исключения из блока catch). Новая функция try-with-resource позволяет получить оба исключения. Более того, вы получите исходное исключение, если исключение из блока finally будет подавлено
Обратите внимание, что когда одно исключение вызывает другое исключение, первое исключение обычно улавливается, а затем возникает второе исключение. Другими словами, существует каузальная связь между двумя исключениями. Напротив, бывают ситуации, когда два независимых исключения могут быть выбраны в блоках кода для сестер, в частности в блоке try оператора try-with-resources и компиляторе, сгенерированном окончательным блоком, который закрывает ресурс. В этих ситуациях можно распространять только одно из заброшенных исключений. В предложении try-with-resources, когда есть два таких исключения, исключение, происходящее из блока try, распространяется, и исключение из блока finally добавляется в список исключений, исключенных из блока try. В качестве исключения разворачивает стек, он может накапливать несколько подавленных исключений.
Пример:
public class TestClass {
static class ResourceA implements AutoCloseable{
public void read() throws Exception{
throw new Exception("ResourceA read exception");
}
@Override
public void close() throws Exception {
throw new Exception("ResourceA close exception");
}
};
static class ResourceB implements AutoCloseable{
public void read() throws Exception{
throw new Exception("ResourceB read exception");
}
@Override
public void close() throws Exception {
throw new Exception("ResourceB close exception");
}
};
//a test method
public static void test() throws Exception{
try (ResourceA a = new ResourceA();
//ResourceB b = new ResourceB()
) {
a.read();
//b.read();
} catch (Exception e) {
throw e;
}
}
public static void main(String[] args) throws Exception {
test();
}
}
Вывод будет следующим:
Exception in thread "main" java.lang.Exception: ResourceA read exception
at TestClass$ResourceA.read(TestClass.java:6)
at TestClass.test(TestClass.java:29)
at TestClass.main(TestClass.java:39)
Suppressed: java.lang.Exception: ResourceA close exception
at TestClass$ResourceA.close(TestClass.java:10)
at TestClass.test(TestClass.java:31)
... 1 more
пакетные задания (массовые операции).
Ну, я нашел некоторое использование этого метода вне try-with-resources. Ниже приведен исходный код из java.net.URLClassLoader.close
public void close() throws IOException { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission(new RuntimePermission("closeClassLoader")); } List<IOException> errors = ucp.closeLoaders(); // now close any remaining streams. synchronized (closeables) { Set<Closeable> keys = closeables.keySet(); for (Closeable c : keys) { try { c.close(); } catch (IOException ioex) { errors.add(ioex); } } closeables.clear(); } if (errors.isEmpty()) { return; } IOException firstex = errors.remove(0); // Suppress any remaining exceptions for (IOException error: errors) { **firstex.addSuppressed(error);** } throw firstex; }
В общем, такой подход может использоваться в пакетных заданиях (массовые операции), когда мы должны перейти к следующему элементу (закрытие следующих открытых потоков, как в этом примере) независимо от того, сработала ли операция над текущим элементом или нет. Таким образом, мы, как я уже заявлял ранее, в некотором роде параллельное выполнение, которое может вызвать исключение, где подавлено. В таких случаях мы должны использовать вышеприведенный подход, чтобы исключить исключение из остающегося в нем исключенного исключения.