Как работает метод getSuppressed()?

Узнал, что если в блоке try с ресурсами было выброшено исключение и в блоке finally было выброшено еще одно, то тогда первоначальное исключение не теряется, а подавляется и его можно получить при помощи метода getSuppressed(). Для проверки этого написал следующий код:

import java.io.*;

class test implements AutoCloseable{
        public void close(){
                throw new RuntimeException();
        }
}

class Main{
        static void qq(){
                try(test q = new test()){
                }
                finally{
                        throw new Error();
                }
        }

        public static void main(String[] args){
                try{
                        qq();
                }
                catch(Throwable a){
                        System.out.println(a.getSuppressed().length);
                }
        }
}

Я ожидал получить 1, но, к удивлению, получил 0.

1.Почему здесь выводится 0, а не 1?

2.Не могли бы вы привести пример где getSuppressed().length выведет больше, чем 0.


Ответы (1 шт):

Автор решения: FatCatStudent

Подавленным исключение в конструкции try-with-resources является исключение, которое выбрасывает метод close, после выброса исключения в теле блока try. При таком раскладе исключение будет добавлено в качестве подавленного автоматически

Пример:

class Test implements AutoCloseable {
    public void close() {
        throw new RuntimeException(); //RE
    }

    public void execute() {
        throw new UnsupportedOperationException(); //UOE
    }
}

public class Main {
    static void testSuppressedExceptions() {
        try (Test test = new Test()) {
            test.execute(); //выбрасывает UOE, является основным
        } //close() выбрасывает RE, является подавленным
    }

    public static void main(String[] args) {
        try {
            testSuppressedExceptions();
        } catch (Throwable e) {
            System.out.println("Main: " + e.getClass());
            System.out.println("Suppressed: " + e.getSuppressed()[0].getClass());
            System.out.println("Suppressed length: " + e.getSuppressed().length);
        }
    }
}

Вывод в консоль:

Main:              class java.lang.UnsupportedOperationException
Suppressed:        class java.lang.RuntimeException
Suppressed length: 1

Получается что основное исключение - UnsupportedOperationException, то что было выброшено в теле, а RuntimeException, которое было выброшено в методе close - подавленное

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

→ Ссылка