«1. Введение
В этом руководстве рассматриваются некоторые распространенные исключения Java.
Мы начнем с обсуждения того, что такое исключение. Позже мы подробно обсудим различные типы проверенных и непроверенных исключений.
2. Исключения
Исключением является ненормальное состояние, возникающее в последовательности кода во время выполнения программы. Это ненормальное состояние возникает, когда программа нарушает определенные ограничения во время выполнения.
Все типы исключений являются подклассами класса Exception. Затем этот класс подразделяется на проверенные исключения и непроверенные исключения. Мы подробно рассмотрим их в следующих разделах.
3. Отмеченные исключения
Отмеченные исключения обязательны для обработки. Они являются прямыми подклассами класса Exception.
Об их важности ведутся споры, на которые стоит обратить внимание.
Давайте подробно определим некоторые проверяемые исключения.
3.1. IOException
Метод генерирует исключение IOException или его прямой подкласс при сбое любой операции ввода/вывода.
Типичные варианты использования этих операций ввода-вывода включают:
-
Работа с файловой системой или потоками данных с помощью пакета java.io Создание сетевых приложений с использованием пакета java.net
FileNotFoundException
FileNotFoundException — распространенный тип IOException при работе с файловой системой:
try {
new FileReader(new File("/invalid/file/location"));
} catch (FileNotFoundException e) {
LOGGER.info("FileNotFoundException caught!");
}
MalformedURLException
При работе с URL-адресами мы можем столкнуться с MalformedURLException — если наши URL-адреса недействительны.
try {
new URL("malformedurl");
} catch (MalformedURLException e) {
LOGGER.error("MalformedURLException caught!");
}
3.2. ParseException
Java использует синтаксический анализ текста для создания объекта на основе заданной строки. Если синтаксический анализ вызывает ошибку, он создает исключение ParseException.
Например, мы могли бы представить дату по-разному, например. дд/мм/гггг или дд,мм,гггг, но попробуйте проанализировать строку в другом формате:
try {
new SimpleDateFormat("MM, dd, yyyy").parse("invalid-date");
} catch (ParseException e) {
LOGGER.error("ParseException caught!");
}
Здесь строка имеет неверный формат и вызывает ParseException.
3.3. InterruptedException
Всякий раз, когда поток Java вызывает функцию join(), sleep() или wait(), он переходит либо в состояние WAITING, либо в состояние TIMED_WAITING.
Кроме того, поток может прервать другой поток, вызвав метод прерывания() другого потока.
Следовательно, поток генерирует InterruptedException, если другой поток прерывает его, пока он находится в состоянии WAITING или TIMED_WAITING.
Рассмотрим следующий пример с двумя потоками:
-
Основной поток запускает дочерний поток и прерывает его Дочерний поток запускается и вызывает sleep()
Этот сценарий приводит к InterruptedException:
class ChildThread extends Thread {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.error("InterruptedException caught!");
}
}
}
public class MainThread {
public static void main(String[] args)
throws InterruptedException {
ChildThread childThread = new ChildThread();
childThread.start();
childThread.interrupt();
}
}
4 Непроверенные исключения
Для непроверенных исключений компилятор не проверяет их в процессе компиляции. Следовательно, методу не обязательно обрабатывать эти исключения.
Все непроверенные исключения расширяют класс RuntimeException.
Давайте подробно обсудим некоторые непроверенные исключения.
4.1. NullPointerException
Если приложение попытается использовать значение null там, где ему действительно требуется экземпляр объекта, метод вызовет исключение NullPointerException.
Существуют различные сценарии, в которых незаконное использование нулевого значения вызывает исключение NullPointerException. Рассмотрим некоторые из них.
Вызов метода класса, у которого нет экземпляра объекта:
String strObj = null;
strObj.equals("Hello World"); // throws NullPointerException.
Кроме того, если приложение пытается получить доступ или изменить переменную экземпляра с нулевой ссылкой, мы получим исключение NullPointerException:
Person personObj = null;
String name = personObj.personName; // Accessing the field of a null object
personObj.personName = "Jon Doe"; // Modifying the field of a null object
4.2. ArrayIndexOutOfBoundsException
Элементы массива хранятся непрерывно. Таким образом, мы можем получить доступ к его элементам через индексы.
Однако, если фрагмент кода пытается получить доступ к недопустимому индексу массива, соответствующий метод выдает исключение ArrayIndexOutOfBoundException.
Давайте рассмотрим несколько примеров, вызывающих исключение ArrayIndexOutOfBoundException:
int[] nums = new int[] {1, 2, 3};
int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
int numFromGreaterIndex = nums[4]; // Trying to access at greater index
int numFromLengthIndex = nums[3]; // Trying to access at index equal to size of the array
4.3. StringIndexOutOfBoundsException
Класс String в Java предоставляет методы для доступа к определенному символу строки или для выделения массива символов из String. Когда мы используем эти методы, внутри он преобразует строку в массив символов.
«Опять же, в этом массиве может иметь место незаконное использование индексов. В таких случаях эти методы класса String вызывают исключение StringIndexOutOfBoundsException.
Это исключение означает, что индекс больше или равен размеру строки. StringIndexOutOfBoundsException расширяет IndexOutOfBoundsException.
Метод charAt(index) класса String выдает это исключение, когда мы пытаемся получить доступ к символу по индексу, равному длине строки, или другому недопустимому индексу:
String str = "Hello World";
char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
char charAtLengthIndex = str.charAt(11); // Trying to access at index equal to size of the string
4.4. NumberFormatException
Довольно часто приложение оказывается с числовыми данными в строке. Чтобы интерпретировать эти данные как числовые, Java позволяет преобразовывать String в числовые типы. Классы-оболочки, такие как Integer, Float и т. д., содержат служебные методы для этой цели.
Однако, если во время преобразования строка не имеет подходящего формата, метод выдает исключение NumberFormatException.
Давайте рассмотрим следующий фрагмент.
Здесь мы объявляем строку с буквенно-цифровыми данными. Далее мы пытаемся использовать методы класса-обертки Integer для интерпретации этих данных как числовых.
Следовательно, это приводит к исключению NumberFormatException:
String str = "100ABCD";
int x = Integer.parseInt(str); // Throws NumberFormatException
int y = Integer.valueOf(str); //Throws NumberFormatException
4.5. ArithmeticException
Когда программа вычисляет арифметическую операцию и в результате возникает какое-то исключительное состояние, она генерирует ArithmeticException. Кроме того, ArithmeticException применяется только к типам данных int и long.
Например, если мы попытаемся разделить целое число на ноль, мы получим ArithmeticException:
int illegalOperation = 30/0; // Throws ArithmeticException
4.6. ClassCastException
Java допускает приведение типов между объектами для поддержки наследования и полиморфизма. Мы можем либо повышать объект, либо понижать его.
При восходящем приведении мы приводим объект к его супертипу. А при понижении мы приводим объект к одному из его подтипов.
Однако во время выполнения, если код пытается преобразовать объект в подтип, экземпляром которого он не является, метод вызывает исключение ClassCastException.
Экземпляр времени выполнения — это то, что действительно важно при приведении типов. Рассмотрим следующее наследование между Animal, Dog и Lion:
class Animal {}
class Dog extends Animal {}
class Lion extends Animal {}
Далее, в классе драйвера мы приводим ссылку Animal, содержащую экземпляр Lion, к Dog.
Однако во время выполнения JVM замечает, что экземпляр Lion несовместим с подтипом класса Dog.
Это приводит к ClassCastException:
Animal animal = new Lion(); // At runtime the instance is Lion
Dog tommy = (Dog) animal; // Throws ClassCastException
4.7. IllegalArgumentException
Метод генерирует исключение IllegalArgumentException, если мы вызываем его с некоторыми недопустимыми или неподходящими аргументами.
Например, метод sleep() класса Thread ожидает положительное время, а мы передаем отрицательный временной интервал в качестве аргумента. Это приводит к исключению IllegalArgumentException:
Thread.currentThread().sleep(-10000); // Throws IllegalArgumentException
4.8. IllegalStateException
IllegalStateException сигнализирует о том, что метод был вызван в недопустимое или неподходящее время.
Каждый объект Java имеет состояние (переменные экземпляра) и некоторое поведение (методы). Таким образом, IllegalStateException означает, что недопустимо вызывать поведение этого объекта с текущими переменными состояния.
Однако с некоторыми другими переменными состояния это может быть допустимо.
Например, мы используем итератор для перебора списка. Всякий раз, когда мы инициализируем его, он внутренне устанавливает для своей переменной состояния lastRet значение -1.
В этом контексте программа пытается вызвать метод удаления из списка:
//Initialized with index at -1
Iterator<Integer> intListIterator = new ArrayList<>().iterator();
intListIterator.remove(); // IllegalStateException
Внутри метод удаления проверяет переменную состояния lastRet и, если она меньше 0, генерирует исключение IllegalStateException. Здесь переменная по-прежнему указывает на значение -1.
В результате мы получаем исключение IllegalStateException.
5. Заключение
В этой статье мы сначала обсудили, что такое исключения. Исключением является событие, происходящее во время выполнения программы, которое нарушает нормальный ход инструкций программы.
Затем мы разделили исключения на проверенные исключения и непроверенные исключения.
Далее мы обсудили различные типы исключений, которые могут возникать во время компиляции или во время выполнения.
«Мы можем найти код для этой статьи на GitHub.