Конструкция try/catch/finally (исключения)

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

Общий вид конструкции

try{
//код, который мы "отслеживаем"
}
catch( myException e ){
//если происходить ошибка, которая соответствует классу myException (наследуется от Exception) 
}
finally{
//выполняется в любом случае (добавлять finnaly не обязательно)
}

Таким образом стоит поместить "проблемный код" внутри блока try и ожидать исключения в блоке catch. Если вам требуется выполнить некую операцию в любом случае, то поместите ваш код в блок finally. Все просто.

Что можно узнать об ошибке?

catch( Exception e ){
    //обрабатываем исключение
}

Ниже приведен список методов, доступных для обработки объекта e (класса Exception).

метод что возвращает что делает
.toString() String возвращает название класса и текст ошибки
.getStackTrace() StackTraceElement[]
.addSuppressed(Throwable exception) void
.fillInStackTrace() Throwable
.getCause() Throwable
.getLocalizedMassage() String возвращает локализованный текст ошибки
.getMessage() String возвращает текст ошибки
.getSuppressed() Throwable[]
.initCase(Throwable cause) Throwable
.printStackTrace() void
.printStackTrace(PrintStream s) void
.printStackTrace(PrintWriter s) void
.setStackTrace(StackTraceElement[] stackTrace) void

* - для вывода ошибок можно использовать отдельный поток (System.err).

▼ Exception.java

Как наследуются исключения

семейство exception

Java требует обрабатывать почти все исключения (Exception), под это правило не попадают исключения, унаследованные от RuntimeException (ошибка выполнения). В остальных же случаях от вас потребуется выбор: обработать ошибку на месте, либо отправить ошибку на уровень выше (для этого используется throw new Exception()).

try{//(1)
    try{//(2)
        int a = 3;
        if ( a > 0 )
            throw new Exception("Text");//try(2) выкинет ошибку на уровень выше
    }
    catch(MyException e){
        System.err.println( "(2): " + e.getMessage() );
    }
}catch(Exception e){
    /* обрабатываем все "вывалившиеся" исключения из try (2) */
    System.err.println( "(1): " + e.getMessage() );
}
//OUTPUT: (1): Text 

*-не обязательные для перехвата

Почему плохо перехватывать сразу через Exception, минуя myException

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

/* передает someException на уровень выше */
public class someClass{
    public static void someMethod() throws someException {
        int a = 5;
        if ( a > 0 )
            throw new someException("some text");
    }
}

Пару слов про finally

Блок finally устроен таким образом, что он будет выполняться в любом случае. Прошу обратить внимание на эти слова, в них спрятано самое интересное:

Что вернет функция getNumber()?

int getNumber(){
    try {
        return 0;
    }
    catch(Exception e){
        return 1;
    }
    finally {
        return 2;
    }
return 3;
}

Ответ: 2.

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

Лучший способ обработки исключений

Если исключение может быть корректно обработано, то его нужно ловить, иначе, оно должно быть проброшено дальше (то есть писать сразу catch(Exception e) не стоит).

Как обрабатывать разные исключение по-разному?

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

Обязательно ли "проверять" все исключения?

Нет, существуют "непроверяемые" исключения, которые не требуется обрабатывать, к примеру: NullPointerException (нулевой указатель) не требует принудительного создания блока try/catch. На диаграмме, приведенной выше, "непроверяемые" исключения обозначены зеленым цветом.

Может ли в конструкторе "вызывать" исключения?

Конечно можно, конструктор такой же метод как и все остальные.

class FileReader{
	public FileInputStream fis = null;
	public FileReader() throws IOException{
		File dir = new File(".");
		File fin = new File(dir.getCanonicalPath() + File.separator + "not-existing-file.txt");
		fis = new FileInputStream(fin);
	}
}

↑ Расскажите друзьям о статье


Comments system Cackle

© EduNow.su — материалы подлежат полному/частичному копированию при указании прямой ссылки на источник. (Сегодня 29.06.17)