Как разработчик Java вы должны хорошо разбираться в исключениях Java и их обработке.
Это руководство предоставляет базовые знания, которые должен иметь каждый программист при работе с программами на Java. Для начала давайте разберемся, что такое исключения Java.
Программа Java может столкнуться с проблемами, в результате которых программа будет внезапно завершена во время ее выполнения. Эти проблемы называются исключениями.
Хороший программист должен уметь распознавать ошибки, которые могут возникнуть во время выполнения, и предоставлять программе альтернативные маршруты в случае возникновения такого исключения. Эта практика называется обработкой исключений.
Теперь вам может быть интересно, зачем нам вообще нужна обработка исключений. Почему бы не писать программы, которые не генерируют исключения?
Оказывается, писать программы, не генерирующие исключения, не так просто, как кажется. В большинстве случаев программист не может контролировать эти неизбежные ошибки.
Программы, которые принимают вводимые пользователем данные, склонны к возникновению исключений из-за неверных вводимых пользователем данных. То же самое и с чтением внешних файлов с учетом вероятности того, что они были перемещены, переименованы или удалены из внешнего источника без ведома программиста.
В таких случаях программа должна уметь корректно обрабатывать исключение, не прерывая выполнение.
Все исключения в Java должны быть дочерними по отношению к Exception
класс, который сам является потомком Throwable
класс.
Два основных подкласса Exception
класс RuntimeException
и IOException
.
Другой дочерний класс Throwable
класс - это Error
класс. Однако ошибки отличаются от исключений.
Ошибки указывают на проблемы, с которыми JVM может столкнуться во время выполнения. Эти проблемы обычно критичны и не подлежат устранению. Утечки памяти и проблемы несовместимости библиотек - частые причины ошибок в программах.
StackOverflowError
и OutOfMemoryError
два примера ошибок Java.
Мы можем разделить исключения Java на две основные категории: проверил а также не отмечен исключения.
Проверенные исключения - это исключения, которые необходимо обработать в программе перед компиляцией. Если эти исключения не обрабатываются, программа не будет скомпилирована компилятором Java. Поэтому их также называют исключениями времени компиляции. IOExceptions
являются хорошими примерами проверенных исключений.
Непроверенные исключения - это исключения, которые компилятор игнорирует при компиляции программы. Обработали ли мы эти исключения в программе или нет, не имеет значения, когда программа компилируется. Поскольку для этих исключений не применяется обработка исключений, наша программа может выполнить RuntimeExceptions
что приводит к завершению программы.
Все классы, расширяющие RuntimeException
class - это непроверенные исключения. Два примера таких классов: NullPointerException
и ArrayIndexOutOfBoundsException
.
Мы рассмотрим несколько часто используемых методов в Java Exception
класс:
getMessage
: возвращает сообщение, содержащее подробную информацию о произошедшем исключении.printStackTrace
: возвращает трассировку стека возникшего исключения.toString
: возвращает имя класса и сообщение, возвращаемое с getMessage
метод.Давайте посмотрим, как мы можем обрабатывать исключения в Java:
Мы можем перехватывать исключения и обрабатывать их должным образом, используя попробуй поймать блок в Java.
В этом синтаксисе часть кода, которая склонна генерировать исключение, помещается внутри блока try, а блок / блоки catch улавливают выброшенное исключение / исключения и обрабатывают их в соответствии с предоставляемой нами логикой.
Базовый синтаксис блока try-catch следующий:
try {
//exception-prone code } catch(Exception e) {
//error handling logic }
При таком подходе программа не останавливает выполнение, когда программа генерирует исключение, вместо этого оно корректно обрабатывается.
Мы увидим, как обращаться с IOExceptions
брошенный FileReader
класс в программе на Java.
Пример:
import java.io.FileReader; public class TryCatchBlockExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader('source.txt');
file.read();
}
catch(Exception e) {
e.printStackTrace();
}
} }
Здесь мы использовали единственный блок catch для обработки FileNotFoundException
выбрасывается при создании экземпляра FileReader
класс и IOException
брошенный read()
метод FileReader
класс.
Оба эти исключения являются потомками Exception
класс.
Мы также можем использовать несколько операторов catch, чтобы перехватывать различные типы ошибок, возникающих из-за кода внутри одного оператора try. В предыдущем примере мы можем использовать один блок catch, чтобы поймать FileNotFoundException
и еще один блок catch для IOException
как показано в следующем фрагменте кода:
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchBlockExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader('source.txt');
file.read();
file.close();
}
catch(FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
} }
Если выброшенное исключение совпадает с исключением, обработанным первым оператором catch, оно затем обрабатывается логикой внутри первого оператора catch.
Если исключения не совпадают, они передаются второму оператору catch. Если имеется более двух операторов catch, этот процесс продолжается до тех пор, пока исключение не достигнет оператора catch, который улавливает его тип.
Поскольку FileNotFoundException
является подтипом IOException
, использующим второй оператор catch для перехвата FileNotFoundException
не сработает. Он будет обработан первым оператором catch и никогда не достигнет второго оператора.
Когда мы используем попробуй поймать блок для перехвата исключений в нашей программе, есть случаи, когда мы хотим реализовать некоторую логику, независимо от того, было перехвачено исключение или нет. В таких случаях мы можем использовать попробовать-поймать-наконец блок, а не просто попробуй поймать блокировать.
Затем код внутри finally
Оператор реализуется независимо от того, происходит ли исключение. finally
оператор всегда должен стоять в конце блока try-catch-finally.
Например, когда мы используем FileReader
Чтобы прочитать файл, важно закрыть открытый файл в конце обработки независимо от того, возникнет ли исключение или нет. Чтобы гарантировать это, мы можем поместить код, закрывающий файл, внутри finally
утверждение.
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;
try {
file = new FileReader('source.txt');
file.read();
}
catch(FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
finally {
file.close();
}
} }
Однако, если вы попытаетесь скомпилировать приведенный выше код, он не будет скомпилирован из-за необработанного IOException
. Это потому, что close()
метод FileReader
класс также может бросать IOExceptions
. Итак, мы должны поместить эту часть в другой блок попытки, например:
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TryCatchFinallyBlockExample {
public static void main(String[] args) {
FileReader file = null;
try {
file = new FileReader('source.txt');
file.read();
}
catch(FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
finally {
try {
file.close();
}
catch(IOException e) {
e.printStackTrace();
}
}
} }
Обработка ошибок с помощью throws
ключевое слово в Java очень просто. Фактически, при таком подходе вы не обрабатываете исключение в том месте, где оно возникает. Вместо этого мы выбрасываем исключение из текущего метода в метод, который вызвал текущий метод. Затем обработка ошибки становится обязанностью внешнего метода.
Чтобы выбросить исключение из метода, вам просто нужно объявить, что этот метод может вызвать рассматриваемое исключение. Посмотрим, как мы справимся с IOExceptions
брошенный FileReader
класс, использующий этот подход.
Пример:
import java.io.FileReader; import java.io.IOException; public class ThrowsExample {
public void readFile throws IOException {
FileReader file = new FileReader('source.txt');
file.read();
file.close();
} }
В отличие от других подходов в этом списке, throw
ключевое слово не используется для обработки ошибок. Но поскольку большинство людей путают throw
ключевое слово с throws
ключевое слово, мы подумали, что лучше обсудить его здесь.
throw
ключевое слово используется для явного вызова исключения. Мы можем выбросить только что созданное исключение или исключение, которое было перехвачено внутри метода.
public class ThrowExample {
public void invalidate(int amount) throws Exception {
if (amount < 500) {
throw new Exception('Amount not sufficient');
}
} }
Помимо использования встроенных исключений Java, вы можете определять свои собственные исключения. Вы можете определить их как отмеченные или непроверенные исключения. Чтобы создать новое проверенное исключение, новое исключение должно расширять Exception
класс.
Чтобы создать незафиксированный исключение, расширить RuntimeException
класс.
В следующем примере кода мы создали определяемое пользователем проверенное исключение:
public class InvalidLengthException extends Exception {
private int length;
private String message;
public InvalidLengthException(int length, String message) {
this.length=length;
this.message=message;
}
public int getAmount() {
return this.length;
}
public String getMessage() {
return this.message;
} }
Теперь мы можем использовать указанное выше исключение внутри нашей программной логики следующим образом:
public class InputChecker {
private int minLength;
private int maxLength;
public InputChecker(int minLength, int maxLength) {
this.minLength=minLength;
this.maxLength=maxLength;
}
public void checkStringLength(String strInput) throws InvalidLengthException {
int strLength = strInput.length();
if (strLength maxLength){
throw new InvalidLengthException(strLength, 'Input should have maximum '+maxLength+' character');
}
} }
Если мы проверим длину строки с помощью InputChecker
класс, он выдаст InvalidLengthException
если длина строки ниже минимальной или выше максимальной.
public class Main {
public static void main(String[] args) {
InputChecker ic = new InputChecker(2, 7);
try {
ic.checkStringLength('longer than the maximum length');
}
catch(InvalidLengthException e) {
e.printStackTrace();
}
} }
Когда мы запускаем приведенный выше фрагмент кода, он выдаст InvalidLengthException
и мы получим следующий результат:
InvalidLengthException: Input should have maximum 7 character
at InputChecker.checkStringLength(InputChecker.java:17)
at Main.main(Main.java:6)
В этом руководстве мы кратко и быстро познакомили вас с исключениями Java. Мы надеемся, что теперь вы хорошо понимаете, что такое исключения и как их обрабатывать в вашей программе Java.