Как сгенерировать ошибку java

To define a checked exception you create a subclass (or hierarchy of subclasses) of java.lang.Exception. For example:

public class FooException extends Exception {
  public FooException() { super(); }
  public FooException(String message) { super(message); }
  public FooException(String message, Throwable cause) { super(message, cause); }
  public FooException(Throwable cause) { super(cause); }
}

Methods that can potentially throw or propagate this exception must declare it:

public void calculate(int i) throws FooException, IOException;

… and code calling this method must either handle or propagate this exception (or both):

try {
  int i = 5;
  myObject.calculate(5);
} catch(FooException ex) {
  // Print error and terminate application.
  ex.printStackTrace();
  System.exit(1);
} catch(IOException ex) {
  // Rethrow as FooException.
  throw new FooException(ex);
}

You’ll notice in the above example that IOException is caught and rethrown as FooException. This is a common technique used to encapsulate exceptions (typically when implementing an API).

Sometimes there will be situations where you don’t want to force every method to declare your exception implementation in its throws clause. In this case you can create an unchecked exception. An unchecked exception is any exception that extends java.lang.RuntimeException (which itself is a subclass of java.lang.Exception):

public class FooRuntimeException extends RuntimeException {
  ...
}

Methods can throw or propagate FooRuntimeException exception without declaring it; e.g.

public void calculate(int i) {
  if (i < 0) {
    throw new FooRuntimeException("i < 0: " + i);
  }
}

Unchecked exceptions are typically used to denote a programmer error, for example passing an invalid argument to a method or attempting to breach an array index bounds.

The java.lang.Throwable class is the root of all errors and exceptions that can be thrown within Java. java.lang.Exception and java.lang.Error are both subclasses of Throwable. Anything that subclasses Throwable may be thrown or caught. However, it is typically bad practice to catch or throw Error as this is used to denote errors internal to the JVM that cannot usually be «handled» by the programmer (e.g. OutOfMemoryError). Likewise you should avoid catching Throwable, which could result in you catching Errors in addition to Exceptions.

Уровень сложности
Простой

Время на прочтение
7 мин

Количество просмотров 3.9K

Исключения являются важной частью любой программы, позволяя элегантно обрабатывать ошибки и исключительные ситуации. В Java, помимо стандартных исключений, разработчики также могут создавать собственные исключения, которые отражают специфические ситуации в их приложениях или библиотеках. В этой статье мы рассмотрим, для чего нужны собственные исключения в Java и как их использовать.

Статья может быть полезна для новичков или тем, кто не так давно в мире Java. В ней мы не касаемся типов исключений, а рассматриваем создание собственных.

Зачем нужны собственные исключения?

Этот вопрос может возникнуть у тех кто только входит в ИТ, и вопрос даже вполне корректный, ведь имеется масса своих исключений, но собственные исключения позволяют разработчикам более гибко управлять ошибками и обрабатывать их в соответствии с требованиями конкретного приложения. Вот несколько причин, по которым собственные исключения в Java могут быть полезны:

1. Отражение специфических ситуаций: Собственные исключения могут быть созданы для отображения конкретных ошибок или ситуаций, которые могут возникнуть в приложении. Например, вы можете создать исключение InvalidInputException, чтобы указать, что получен недопустимый ввод от пользователя.

2. Локализация и обработка ошибок: Собственные исключения позволяют локализовать и обрабатывать ошибки на определенном уровне в коде. Каждое исключение может быть обработано отдельно, что упрощает отладку и обработку ошибок.

3. Гибкая обработка и восстановление: При использовании собственных исключений вы можете предоставить гибкую обработку ошибок, включая восстановление после ошибки или выполнение альтернативных действий. Например, вы можете перехватить исключение FileNotFoundException и попробовать открыть альтернативный файл.

4. Инкапсуляция ошибок: Собственные исключения позволяют инкапсулировать информацию об ошибке и передавать ее на более высокий уровень в коде. Это помогает упростить код и улучшить его читаемость, так как обработка ошибок может быть сосредоточена в одном месте.

5. Расширение стандартных исключений: Собственные исключения могут расширять стандартные исключения Java, такие как Exception или RuntimeException, чтобы добавить дополнительную информацию или функциональность при обработке ошибок. Например, вы можете создать исключение DatabaseException, которое расширяет Exception и содержит дополнительные методы для работы с базой данных.

Примеры создания собственных исключений

Пример 1

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

public class InvalidInputException extends Exception {
    public InvalidInputException(String message) {
        super(message);
    }
}

В этом примере класс InvalidInputException расширяет класс Exception и имеет конструктор, который принимает сообщение об ошибке в качестве параметра. В конструкторе вызывается конструктор суперкласса Exception, передавая ему сообщение.

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

public class Example {
    public static void main(String[] args) {
        try {
            validateInput("abc");
        } catch (InvalidInputException e) {
            System.out.println("Invalid input: " + e.getMessage());
        }
    }

    public static void validateInput(String input) throws InvalidInputException {
        if (input == null || input.isEmpty()) {
            throw new InvalidInputException("Input cannot be null or empty");
        }
    }
}

В этом примере метод validateInput() проверяет, является ли входная строка пустой или равной null. Если это так, то метод выбрасывает исключение InvalidInputException с сообщением. В методе main() мы вызываем validateInput() с недопустимым вводом и перехватываем исключение с помощью блока catch, где выводим сообщение об ошибке.

Пример 2

// Создаем собственное исключение
class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

// Класс, который использует собственное исключение
class Example {
    // Метод, который может выбросить собственное исключение
    public static void doSomething(int value) throws CustomException {
        if (value < 0) {
            throw new CustomException("Значение должно быть больше или равно нулю");
        }
    }

    public static void main(String[] args) {
        try {
            // Вызываем метод, который может выбросить исключение
            doSomething(-5);
        } catch (CustomException e) {
            // Обрабатываем исключение
            System.out.println("Ошибка: " + e.getMessage());
        }
    }
}

В этом примере у нас есть метод doSomething, который может выбросить собственное исключение CustomException, если значение аргумента меньше нуля. В методе main мы вызываем этот метод с отрицательным значением и перехватываем исключение с помощью блока catch. Затем мы выводим сообщение об ошибке.

Этот пример показывает, как правильно объявлять методы, которые могут выбрасывать собственные исключения, и как перехватывать их при вызове этих методов

Пример 3

// Создаем собственное исключение
class InvalidEmailException extends Exception {
    public InvalidEmailException(String message) {
        super(message);
    }
}

// Класс, который использует собственное исключение
class EmailValidator {
    // Метод, который может выбросить собственное исключение
    public static void validateEmail(String email) throws InvalidEmailException {
        if (!email.contains("@")) {
            throw new InvalidEmailException("Некорректный адрес электронной почты");
        }
    }

    public static void main(String[] args) {
        try {
            // Вызываем метод, который может выбросить исключение
            validateEmail("example.com");
        } catch (InvalidEmailException e) {
            // Обрабатываем исключение
            System.out.println("Ошибка: " + e.getMessage());
        }
    }
}

В этом примере у нас есть метод validateEmail, который может выбросить собственное исключение InvalidEmailException, если переданный адрес электронной почты не содержит символа «@». В конструкторе исключения мы передаем сообщение об ошибке. В методе main мы вызываем этот метод с некорректным адресом электронной почты и перехватываем исключение с помощью блока catch. Затем мы выводим сообщение об ошибке.

Вот вроде бы и все, достаточно легко и просто, как всегда, есть одно большое но! можно создать исключения, которые только усложнят жизнь разработку

Пример 4 (некорректное создание исключений)

// Некорректное создание собственного исключения
class MyException extends Exception {
    public MyException() {
        super();
    }
}

В этом примере мы создаем собственное исключение MyException, но не передаем ему сообщение об ошибке через конструктор. Это может привести к непонятным или неинформативным сообщениям об ошибках при перехвате исключения.

Корректным подходом будет передача сообщения об ошибке через конструктор, как показано в предыдущем примере:

class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }
}

Таким образом, при выбрасывании и перехвате исключения MyException будет доступно информативное сообщение об ошибке.

Пример 5 (некорректное использование)

Примером неправильного использования собственного исключения может быть его применение без реальной необходимости или создание избыточных иерархий исключений.

public class MyCustomException extends Exception {
    // ...
}

public class Example {
    public static void main(String[] args) {
        try {
            throw new MyCustomException();
        } catch (MyCustomException e) {
            System.out.println("Caught MyCustomException");
        } catch (Exception e) {
            System.out.println("Caught Exception");
        }
    }
}

В этом примере мы создаем собственное исключение MyCustomException, но в блоке catch обрабатываем его так же, как и любое другое исключение Exception. Такое использование собственного исключения делает его бессмысленным, поскольку нет никакой разницы между обработкой MyCustomException и обработкой любого другого исключения.

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

Плюсы создания собственных исключений:

1. Отражение специфических ситуаций: Собственные исключения позволяют точно отражать конкретные ошибки или ситуации, которые могут возникнуть в вашем приложении. Это упрощает понимание и обработку ошибок другими разработчиками, которые работают с вашим кодом.

2. Гибкая обработка и восстановление: Использование собственных исключений позволяет предоставить гибкую обработку ошибок, включая восстановление после ошибки или выполнение альтернативных действий. Это помогает повысить надежность и стабильность вашего приложения.

3. Инкапсуляция информации об ошибке: Собственные исключения позволяют инкапсулировать информацию об ошибке, включая дополнительные детали или контекст ошибки. Это помогает упростить код и улучшить его читаемость, так как обработка ошибок может быть сосредоточена в одном месте.

4. Расширение стандартных исключений: Вы можете расширять стандартные исключения Java, такие как Exception или RuntimeException, с добавлением дополнительной функциональности или информации для обработки ошибок. Это позволяет вам более точно определить тип ошибки и предоставить дополнительные методы для работы с ней.

Минусы создания собственных исключений:

1. Усложнение кода: Создание собственных исключений может привести к усложнению кода, особенно если их необходимо обрабатывать на разных уровнях в приложении. Слишком много разных исключений может сделать код сложным для чтения и понимания.

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

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

4. Проблемы совместимости: Если вы используете собственные исключения в библиотеке или API, это может создать проблемы совместимости, если другие разработчики не знакомы с вашими исключениями или не знают, как с ними работать.

Заключение

Собственные исключения в Java предоставляют разработчикам возможность более гибко управлять ошибками и исключительными ситуациями в своих приложениях или библиотеках. Они позволяют отразить специфические ситуации, локализовать и обработать ошибки, предоставить гибкую обработку и восстановление, инкапсулировать ошибки и расширить стандартные исключения.

Исключение (exception) — это ненормальная ситуация (термин «исключение» здесь следует понимать как «исключительная ситуация»), возникающая во время выполнения программного кода. Иными словами, исключение — это ошибка, возникающая во время выполнения программы (в runtime).

Исключение — это способ системы Java (в частности, JVM — виртуальной машины Java) сообщить вашей программе, что в коде произошла ошибка. К примеру, это может быть деление на ноль, попытка обратиться к массиву по несуществующему индексу, очень распространенная ошибка нулевого указателя (NullPointerException) — когда вы обращаетесь к ссылочной переменной, у которой значение равно null и так далее.

В любом случае, с формальной точки зрения, Java не может продолжать выполнение программы.

Обработка исключений (exception handling) — название объектно-ориентированной техники, которая пытается разрешить эти ошибки.

Программа в Java может сгенерировать различные исключения, например:

  • программа может пытаться прочитать файл из диска, но файл не существует;

  • программа может попытаться записать файл на диск, но диск заполнен или не отформатирован;

  • программа может попросить пользователя ввести данные, но пользователь ввел данные неверного типа;

  • программа может попытаться осуществить деление на ноль;

  • программа может попытаться обратиться к массиву по несуществующему индексу.

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

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

В Java все исключения представлены отдельными классами. Все классы исключений являются потомками класса Throwable. Так, если в программе возникнет исключительная ситуация, будет сгенерирован объект класса, соответствующего определенному типу исключения. У класса Throwable имеются два непосредственных подкласса: Exception и Error.

Исключения типа Error относятся к ошибкам, возникающим в виртуальной машине Java, а не в прикладной программе. Контролировать такие исключения невозможно, поэтому реакция на них в приложении, как правило, не предусматривается. В связи с этим исключения данного типа не будут рассматриваться в книге.

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

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


Так как в Java
ВСЁ ЯВЛЯЕТСЯ ОБЪЕКТОМ, то исключение тоже является объектом некоторого класса, который описывает исключительную ситуацию, возникающую в определенной части программного кода.

«Обработка исключений» работает следующим образом:

  • когда возникает исключительная ситуация, JVM генерирует (говорят, что JVM ВЫБРАСЫВАЕТ исключение, для описания этого процесса используется ключевое слово throw) объект исключения и передает его в метод, в котором произошло исключение;

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

  • таким образом, если возникнет ошибка, все необходимые действия по ее обработке выполнит обработчик исключений.

Если вы не предусмотрите обработчик исключений, то исключение будет перехвачено стандартным обработчиком Java. Стандартный обработчик прекратит выполнение программы и выведет сообщение об ошибке.

Рассмотрим пример исключения и реакцию стандартного обработчика Java.

public static void main(String[] args) {

System.out.println(5 / 0);

Мы видим, что стандартный обработчик вывел в консоль сообщение об ошибке. Давайте разберемся с содержимым этого сообщения:

«C:\Program Files\Java\jdk1.8.0_60\bin\java»

Exception in thread «main» java.lang.ArithmeticException: / by zero

at ua.opu.Main.main(Main.java:6)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 1

Exception in thread «main» java.lang.ArithmeticException: / by zero

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

at ua.opu.Main.main(Main.java:6)

в каком классе, методе и строке произошло исключение. Используя эту информацию, мы можем найти ту строчку кода, которая привела к исключительной ситуации, и предпринять какие-то действия. Строки

at ua.opu.Main.main(Main.java:6)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:497)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

называются «трассировкой стека» (stack tracing). О каком стеке идет речь? Речь идет о стеке вызовов (call stack). Соответственно, эти строки означают последовательность вызванных методов, начиная от метода, в котором произошло исключение, заканчивая самым первым вызванным методом.

Для вызова методов в программе используется инструкция «call». Когда вы вызываете метод в программе, важно сохранить адрес следующей инструкции, чтобы, когда вызванный метод отработал, программа продолжила работу со следующей инструкции. Этот адрес нужно где-то хранить в памяти. Также перед вызовом необходимо сохранить аргументы функции, которые тоже необходимо где-то хранить.

Вся эта информация хранится в специальной структуре – стеке вызовов. Каждая запись в стеке вызовов называется кадром или фреймом (stack frame).

Таким образом, зная, какая строка привела к возникновению исключения, вы можете изменить код либо предусмотреть обработчик событий.

Как уже было сказано выше, исключение это объект некоторого класса. В Java существует разветвленная иерархия классов исключений.

В Java, класс исключения служит для описания типа исключения. Например, класс NullPointerException описывает исключение нулевого указателя, а FileNotFoundException означает исключение, когда файл, с которым пытается работать приложение, не найден. Рассмотрим иерархию классов исключений:

На самом верхнем уровне расположен класс Throwable, который является базовым для всех исключений (как мы помним, JVM «выбрасывает» исключение», поэтому класс Throwable означает – то, что может «выбросить» JVM).

От класса Throwable наследуются классы Error и Exception. Среди подклассов Exception отдельно выделен класс RuntimeException, который играет важную роль в иерархии исключений.

В Java существует некоторая неопределенность насчет того – существует ли два или три вида исключений.

Если делить исключения на два вида, то это:

  1. 1.

    контролируемые исключения (checked exceptions) – подклассы класса Exception, кроме подкласса RuntimeException и его производных;

  2. 2.

    неконтролируемые исключения (unchecked exceptions) – класс Error с подклассами, а также класс RuntimeException и его производные;

В некоторых источниках класс Error и его подклассы выделяют в отдельный вид исключений — ошибки (errors).

Далее мы видим класс Error. Классы этой ветки составляют вид исключений, который можно обозначить как «ошибки» (errors). Ошибки представляют собой серьезные проблемы, которые не следует пытаться обработать в собственной программе, поскольку они связаны с проблемами уровня JVM.

На самом деле, вы конечно можете предпринять некоторые действия при возникновении ошибок, например, вывести сообщение для пользователя в удобном формате, выслать трассировку стека себе на почту, чтобы понять – что вообще произошло.

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

В качестве примеров «ошибок» можно привести: переполнение стека вызова (класс StackOverflowError); нехватка памяти в куче (класс OutOfMemoryError), вследствие чего JVM не может выделить память под новый объект и сборщик мусора не помогает; ошибка виртуальной машины, вследствие которой она не может работать дальше (класс VirtualMachineError) и так далее.

Несмотря на то, что в нашей программе мы никак не можем помочь этой проблеме, и приложение не может работать дальше (ну как может работать приложение, если стек вызовов переполнен или JVM не может дальше выполнять код?!); знание природы этих ошибок поможет вам предпринять некоторые действия, чтобы избежать этих ошибок в дальнейшем. Например, ошибки типа StackOverflowError и OutOfMemoryError могут быть следствием вашего некорректного кода.

Например, попробуем спровоцировать ошибку StackOverflowError

public static void main(String[] args) {

public static void methodA() {

private static void methodB() {

Получим такое сообщение об ошибке

Exception in thread «main» java.lang.StackOverflowError

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

at com.company.Main.methodB(Main.java:14)

at com.company.Main.methodA(Main.java:10)

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

Exception in thread «main» java.lang.OutOfMemoryError: Java heap space

at java.base/java.util.Arrays.copyOf(Arrays.java:3511)

at java.base/java.util.Arrays.copyOf(Arrays.java:3480)

at java.base/java.util.ArrayList.grow(ArrayList.java:237)

at java.base/java.util.ArrayList.grow(ArrayList.java:244)

at java.base/java.util.ArrayList.add(ArrayList.java:454)

at java.base/java.util.ArrayList.add(ArrayList.java:467)

at com.company.Main.main(Main.java:13)

Process finished with exit code 1

Ошибка VirtualMachineError может означать, что следует переустановить библиотеки Java.

В любом случае, следует относиться к типу Error не как к неизбежному злу и «воле богов», а просто как к сигналу к тому, что в вашем приложении что-то не так, или что-то не так с программным или аппаратным обеспечением, которое вы используете.

Класс Exception описывает исключения, связанные непосредственно с работой программы. Такого рода исключения «решаемы» и их грамотная обработка позволит программе работать дальше в нормальном режиме.

В классе Exception описаны исключения двух видов: контролируемые исключения (checked exceptions) и неконтролируемые исключения (unchecked exceptions).

Неконтролируемые исключения содержатся в подклассе RuntimeException и его наследниках. Контролируемые исключения содержатся в остальных подклассах Exception.

В чем разница между контролируемыми и неконтролируемыми исключениями, мы узнаем позже, а теперь рассмотрим вопрос – а как же именно нам обрабатывать исключения?

Обработка исключений в методе может выполняться двумя способами:

  1. 1.

    с помощью связки try-catch;

  2. 2.

    с помощью ключевого слова throws в сигнатуре метода.

Рассмотрим оба метода поподробнее:

Способ 1. Связка try-catch

Этот способ кратко можно описать следующим образом.

Код, который теоретически может вызвать исключение, записывается в блоке try{}. Сразу за блоком try идет блок код catch{}, в котором содержится код, который будет выполнен в случае генерации исключения. В блоке finally{} содержится код, который будет выполнен в любом случае – произошло ли исключение или нет.

Теперь разберемся с этим способом более подробно. Рассмотрим следующий пример – программу, которая складывает два числа, введенные пользователем из консоли

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

System.out.println(«Введите первое число: «);

String firstNumber = scanner.nextLine();

System.out.println(«Введите второе число: «);

String secondNumber = scanner.nextLine();

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

System.out.println(«Результат: « + (a + b));

Первое, что нам нужно определить – и что является главным при работе с исключениями, КАКАЯ ИНСТРУКЦИЯ МОЖЕТ ПРИВЕСТИ К ВОЗНИКНОВЕНИЮ ИСКЛЮЧЕНИЯ?

То есть, мы должны понять – где потенциально у нас может возникнуть исключение? Понятно, что речь идет не об операции сложения и не об операции чтения данных из консоли. Потенциально опасными строчками кода здесь являются строчки

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

в которых происходит преобразование ввода пользователя в целое число (метод parseInt() преобразует цифры в строке в число).

Почему здесь может возникнуть исключение? Потому что пользователь может ввести не число, а просто какой-то текст и тогда непонятно – что записывать в переменную a или b. И да, действительно, если пользователь введет некорректное значение, возникнет исключение в методе Integer.parseInt().

Итак, что мы можем сделать. «Опасный код» нужно поместить в блок try{}

Обратите внимание на синтаксис блока try. В самом простом случае это просто ключевое слово try, после которого идут парные фигурные скобки. Внутри этих скобок и заключается «опасный» код, который может вызвать исключение. Сразу после блока try должен идти блок catch().

a = Integer.parseInt(firstNumber);

b = Integer.parseInt(secondNumber);

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

System.out.println(«Результат: « + (a + b));

Обратите внимание на синтаксис блока catch. После ключевого слова, в скобках описывается аргумент с именем e типа NumberFormatException.

Когда произойдет исключение, то система Java прервет выполнение инструкций в блоке try и передаст управление блоку catch и запишет в этот аргумент объект исключения, который сгенерировала Java-машина.

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

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

Блок catch сработает только в том случае, если указанный в скобках тип объекта исключения будет суперклассом или будет того же типа, что и объект исключения, который сгенерировала Java.

Например, если в нашем примере мы напишем код, который потенциально может выбросить исключение типа IOException, но не изменим блок catch

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

тогда обработчик не будет вызван и исключение будет обработано стандартным обработчиком Java.

Способ 2. Использование ключевого слова throws

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

Изменим наш пример и выделим в отдельный метод код, который будет запрашивать у пользователя число и возвращать его как результат работы метода

public static void main(String[] args) {

int a = getNumberFromConsole(«Введите первое число»);

int b = getNumberFromConsole(«Введите второе число»);

System.out.println(«Результат: « + (a + b));

public static int getNumberFromConsole(String message) {

Scanner scanner = new Scanner(System.in);

System.out.print(message + «: «);

String s = scanner.nextLine();

return Integer.parseInt(s);

Мы понимаем, что в данном методе может произойти исключение, но мы не хотим или не можем его обработать. Причины могут быть разными, например:

  1. 1.

    обработка исключений может происходить централизованно однотипным способом (например, показ окошка с сообщением и с определенным текстом);

  2. 2.

    это не входит в нашу компетенцию как программиста – обработкой исключений занимается другой программист;

  3. 3.

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

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

public static int getNumberFromConsole(String message) throws NumberFormatException {

Scanner scanner = new Scanner(System.in);

System.out.print(message + «: «);

String s = scanner.nextLine();

return Integer.parseInt(s);

Обратите внимание на расположение сигнатуру метода. Мы привыкли, что при объявлении метода сразу после скобок входных аргументов мы открываем фигурную скобку и записываем тело метода. Здесь же, после входных аргументов, мы пишем ключевое слово throws и потом указываем тип исключения, которое может быть сгенерировано в нашем методе. Если метод может выбрасывать несколько типов исключений, они записываются через запятую

public static void foo() throws NumberFormatException, ArithmeticException, IOException {

Тогда, в методе main мы должны написать примерно следующее

public static void main(String[] args) {

a = getNumberFromConsole(«Введите первое число»);

b = getNumberFromConsole(«Введите второе число»);

} catch (NumberFormatException e) {

// сохранить текст ошибки в лог

System.out.println(«Одно или оба значения некорректны!»);

System.out.println(«Результат: « + (a + b));

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

Отличия между контролируемыми и неконтролируемыми исключениями

Если вы вызываете метод, который выбрасывает checked исключение, то вы ОБЯЗАНЫ предусмотреть обработку возможного исключения, то есть связку try-catch.

Яркий пример checked исключения – класс IOException и его подклассы.

Рассмотрим пример – попробуем прочитать файл и построчно вывести его содержимое на экран консоли:

public static void main(String[] args) {

Path p = Paths.get(«c:\\temp\\file.txt»);

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Как мы видим, компилятор не хочет компилировать наш код. Чем же он недоволен? У нас в коде происходит вызов двух методов – статического метода Files.newBufferedReader() и обычного метода BufferedReader.readLine().

Если посмотреть на сигнатуры этих методов то можно увидеть, что оба этих метода выбрасывают исключения типа IOException. Этот тип исключения относится к checked-исключению и поэтому, если вы вызываете эти методы, компилятор ТРЕБУЕТ от вас предусмотреть блок catch, либо в самом вашем методе указать throws IOException и, таким образом, передать обязанность обрабатывать исключение другому методу, который будет вызывать ваш.

Таким образом, «оборачиваем» наш код в блок try и пишем блок catch.

public static void main(String[] args) {

Path p = Paths.get(«c:\\temp\\file.txt»);

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

Еще один способ — указать в сигнатуре метода, что он выбрасывает исключение типа IOException и переложить обязанность обработать ошибку в вызывающем коде

public static void main(String[] args) {

Path p = Paths.get(«c:\\temp\\file.txt»);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

public static void printFile(Path p) throws IOException {

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Eсли метод выбрасывает checked-исключение, то проверка на наличие catch-блока происходит на этапе компиляции. И вы обязаны предусмотреть обработку исключения для checked-исключения.

Что касается unchecked-исключения, то обязательной обработки исключения нет – вы можете оставить подобные ситуации без обработки.

Зачем необходимо наличие двух видов исключений?

В большинстве языков существует всего лишь один тип исключений – unchecked. Некоторые языки, например, C#, в свое время отказались от checked-исключений.

Во-первых, мы не можем сделать все исключения checked, т.к. очень многие операции могут генерировать исключения, и если каждый такой участок кода «оборачивать» в блок try-catch, то код получится слишком громоздким и нечитабельным.

С другой стороны, зачем нужно делать некоторые типы исключений checked? Почему просто не сделать все исключения unchecked и оставить решения об обработке исключений целиком на совести программиста?

В официальной документации написано, что unchecked-исключения – это те исключения, от которых программа «не может восстановиться», тогда как checked-исключения позволяют откатить некоторую операцию и повторить ее снова.

На самом деле, если вы посмотрите на различные типы unchecked-исключений, то вы увидите, что большинство их связаны с ошибками самого программиста. Выход за пределы массива, исключение нулевого указателя, деление на ноль – большинство из подобного рода исключений целиком лежат на совести программистов. Тогда мы можем сказать, что лучше программист пишет более хороший код, чем везде вставляет проверки на исключения.

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

Вы можете написать идеальный код, но потом вы отдадите приложение пользователю, а он введет название файла, которого нет или напишет неправильный IP для сокет-соединения. Таким образом, мы заранее должны быть готовыми к неверным действиям пользователя или к программным или аппаратным проблемам на его стороне и в обязательном порядке предусмотреть обработку возможных исключений.

Дополнительно об исключениях

Рассмотрим детально различные возможности механизма исключений, которые позволяют программисту максимально эффективно противодействовать исключениям:

Java позволяет вам для одного блока try предусмотреть несколько блоков catch, каждый из которых должен обрабатывать свой тип исключения

public static void foo() {

} catch (ArithmeticException e) {

// обработка арифметического исключения

} catch (IndexOutOfBoundsException e) {

// обработка выхода за пределы коллекции

} catch (IllegalArgumentException e) {

// обработка некорректного аргумента

Важно помнить, что Java обрабатывает исключения последовательно. Java просматривает блок catch сверху вниз и выполняет первый подходящий блок, который может обработать данное исключение.

Так как вы можете указать как точный класс, так и суперкласс, то если первым блоком будет блок для суперкласса – выполнится он. Например, исключение FileNotFoundException является подклассом IOException. И поэтому если вы первым поставите блок с IOException – он будет вызываться для всех подтипов исключений, в том числе и для FileNotFoundException и блок c FileNotFoundException никогда не выполнится.

public static void main(String[] args) {

Path p = Paths.get(«c:\\temp\\file.txt»);

} catch (IOException e) {

System.out.println(«Ошибка при чтении файла!»);

} catch (FileNotFoundException e) {

// данный блок никогда не будет вызван

public static void printFile(Path p) throws IOException {

BufferedReader reader = Files.newBufferedReader(p);

while ((line = reader.readLine()) != null) {

System.out.println(line);

Один блок для обработки нескольких типов исключений

Начиная с версии Java 7, вы можете использовать один блок catch для обработки исключений нескольких, не связанных друг с другом типов. Приведем пример

public static void foo() {

} catch (ArithmeticException | IllegalArgumentException | IndexOutOfBoundsException e) {

// три типа исключений обрабатываются одинаково

Как мы видим, один блок catch используется для обработки и типа IOException и NullPointerException и NumberFormaException.

Вы можете использовать вложенные блоки try, которые могут помещаться в других блоках try. После вложенного блока try обязательно идет блок catch

public static void foo() {

} catch (IllegalArgumentException e) {

// обработка вложенного блока try

} catch (ArithmeticException e) {

Выбрасывание исключения с помощью ключевого слова throw

С помощью ключевого слова throw вы можете преднамеренно «выбросить» определенный тип исключения.

public static void foo(int a) {

throw new IllegalArgumentException(«Аргумент не может быть отрицательным!»);

Кроме блока try и catch существует специальный блок finally. Его отличительная особенность – он гарантированно отработает, вне зависимости от того, будет выброшено исключение в блоке try или нет. Как правило, блок finally используется для того, чтобы выполнить некоторые «завершающие» операции, которые могли быть инициированы в блоке try.

public static void foo(int a) {

FileOutputStream fout = null;

File file = new File(«file.txt»);

fout = new FileOutputStream(file);

} catch (IOException e) {

// обработка исключения при записи в файл

} catch (IOException e) {

При любом развитии события в блоке try, код в блоке finally отработает в любом случае.

Блок finally отработает, даже если в try-catch присутствует оператор return.

Как правило, блок finally используется, когда мы в блоке try работаем с ресурсами (файлы, базы данных, сокеты и т.д.), когда по окончании блока try-catch мы освобождаем ресурсы. Например, допустим, в процессе работы программы возникло исключение, требующее ее преждевременного закрытия. Но в программе открыт файл или установлено сетевое соединение, а, следовательно, файл нужно закрыть, а соединение – разорвать. Для этого удобно использовать блок finally.

Блок try-with-resources является модификацией блока try. Данный блок позволяет автоматически закрывать ресурс после окончания работы блока try и является удобной альтернативой блоку finally.

public static void foo() {

Path p = Paths.get(«c:\\temp\\file.txt»);

try (BufferedReader reader = Files.newBufferedReader(p)) {

while ((line = reader.readLine()) != null)

System.out.println(line);

} catch (IOException e) {

Внутри скобок блока try объявляется один или несколько ресурсов, которые после отработки блока try-catch будут автоматически освобождены. Для этого объект ресурса должен реализовывать интерфейс java.lang.AutoCloseable.

Создание собственных подклассов исключений

Встроенные в Java исключения позволяют обрабатывать большинство распространенных ошибок. Тем не менее, вы можете создавать и обрабатывать собственные типы исключений. Для того, чтобы создать класс собственного исключения, достаточно определить как его произвольный от Exception или от RuntimeException (в зависимости от того, хотите ли вы использовать checked или unchecked – исключения).

Насчет создания рекомендуется придерживаться двух правил:

  1. 1.

    определитесь, исключения какого типа вы хотите использовать для собственных исключений (checked или unchecked) и старайтесь создавать исключения только этого типа;

  2. 2.

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

Плохие практики при обработке исключений

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

  1. 1.

    Указание в блоке catch объекта исключения типа Exception. Существует очень большой соблазн при создании блока catch указать тип исключения Exception и, таким образом, перехватывать все исключения, которые относятся к этому классу (а это все исключения, кроме системных ошибок). Делать так крайне не рекомендуется, т.к. вместо того чтобы решать проблему с исключениями, мы фактически игнорируем ее и просто реализуем некоторую «заглушку», чтобы приложение продолжило работу дальше. Кроме того, каждый тип исключения должен быть обработан своим определенным образом.

  2. 2.

    Помещение в блок try всего тела метода. Следующий плохой прием используется, когда программист не хочет разбираться с кодом, который вызывает исключение и просто, опять же, реализует «заглушку». Этот прием очень «хорошо» сочетается с первым приемом. В блок try должен помещаться только тот код, который потенциально может вызвать исключение, а не всё подряд, т.к. лень обрабатывать исключения нормально.

  3. 3.

    Игнорирование исключения. Следующий плохой прием состоит в том, что мы просто игнорируем исключение и оставляем блок catch пустым. Программа должна реагировать на исключения и должна информировать пользователя и разработчика о том, что что-то пошло не так. Безусловно, исключение это не повод тут же закрывать приложение, а попытаться повторить то действие, которое привело к исключению (например, повторно указать название файла, попытаться открыть базу данных через время и т.д.). В любом случае, когда приложение в ответ на ошибку никак не реагирует – не выдает сообщение, но и не делает того, чего от нее ожидали – это самый плохой вариант.

Java. Исключения. Операторы throw, throws. Примеры

Изучение данной темы базируется на использовании следующих тем:

  • Понятие об исключении. Конструкция try…catch…finally
  • Классы Java для обработки исключительных ситуаций.

Содержание

  • 1. Какое назначение ключевого слова throw? Общая форма
  • 2. Пример генерирования исключения с помощью оператора throw в блоке try. Создание класса, который решает квадратное уравнение
  • 3. Какие типы запрещено использовать для генерирования исключений оператором throw?
  • 4. Каким образом создать собственный класс исключения? Пример
  • 5. Какое назначение ключевого слова throws? Общая форма
  • 6. Пример использования оператора throws для метода, который генерирует исключение
  • Связанные темы

Поиск на других ресурсах:

1. Какое назначение ключевого слова throw? Общая форма

Исключение может генерировать:

  • исполняющая среда Java;
  • прикладная программа. В этом случае программа должна использовать оператор throw.

Общая форма оператора throw имеет следующий вид

throw instance;

здесь instance – объект класса Throwable или производного от него подкласса. Более подробно о классе Throwable можно просмотреть здесь.

Если оператор throw используется в блоке try…catch, то в общем вид блока следующий

...
try {
    // ...
    throw new ThrowableClass(parameters); // если исключительная ситуация, то сгенерировать исключение
    // ...
}
catch (ThrowableClass e) {
    // обработать исключение
    // ...
}
...

здесь

  • ThrowableClass – класс, производный от класса Throwable или RunTimeException;
  • e – экземпляр класса, который соответствует перехватываемому исключению;
  • parameters – параметры конструктора класса ThrowableClass. Как правило, конструкторы классов производных от Throwable или RunTimeException имеют два варианта реализации: без параметров или с одним строчным параметром, который описывает исключительную ситуацию.

В строке

throw new ThrowableClass(parameters);

создается исключение с помощью оператора new, который выделяет память и вызывает конструктор. Для всех стандартных исключений существует два конструктора:

  • конструктор по умолчанию. Этот конструктор не содержит параметров;
  • конструктор с одним параметром, который представляет собой строку. В строке указывается информация об исключении. Например, строка «деление на ноль».

 

2. Пример генерирования исключения с помощью оператора throw в блоке try. Создание класса, который решает квадратное уравнение

Генерирование исключения осуществляется с помощью ключевого слова throw, которое может встречаться в блоке try (генерирование исключения вручную). Например, приведенный ниже код демонстрирует пример генерирования исключения вручную с помощью средства throw.

Объявляется класс QuadraticEquation который решает квадратное уравнение.

В классе объявляются следующие элементы:

  • внутренние переменные a, b, c которые есть коэффициентами уравнения;
  • внутренние переменные x1, x2 которые есть решениями уравнения (в случае, если уравнение имеет решение);
  • конструктор класса;
  • метод Solution(). В этом методе используется обработка возможных исключительных ситуаций: деление на 0 и корень из отрицательного числа.

Текст класса следующий:

// генерирование исключения оператором throw
// решение квадратного уравнения
class QuadraticEquation {
    double a,b,c,x1,x2;

    // конструктор
    QuadraticEquation(double a, double b, double c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    // метод, который решает квадратное уравнение
    void Solution() {
        double d; // дискриминант

        try {
            d = b*b - 4*a*c;

            // учесть деление на 0
            if (a==0)
                throw new ArithmeticException("Деление на 0."); // создать исключение

            // учесть корень из отрицательного числа
            if (d<0)
                throw new ArithmeticException("Уравнение не имеет корней."); // создать исключение

            x1 = (-b - Math.sqrt(d))/(2*a);
            x2 = (-b + Math.sqrt(d))/(2*a);

            System.out.println("x1 = " + x1);
            System.out.println("x2 = " + x2);
        }
        catch (ArithmeticException e) {
            System.out.println(e); // вывести исключение, созданное в блоке try
        }
    }
}

В методе Solution() перехватываются две исключительных ситуации:

  • деление на 0;
  • корень из отрицательного числа.

Для этого с помощью оператора throw создается соответствующий экземпляр класса ArithmeticException. Класс ArithmeticException есть подклассом класса RuntimeException. Класс ArithmeticException используется если возникла арифметическая ошибка. В нашем случае имеем арифметические ошибки двух видов:

  • деление на 0;
  • корень из отрицательного числа.

Поэтому, в блоке try создается соответствующий экземпляр исключения со строкой описания ошибки

...
// учесть деление на 0
if (a==0)
    throw new ArithmeticException("Деление на 0."); // создать исключение

// учесть корень из отрицательного числа
if (d<0)
    throw new ArithmeticException("Уравнение не имеет корней."); // создать исключение
...

Обработка любой из ошибок в операторе catch есть стандартной. Поэтому, просто выводится текст описания исключения

...
catch (ArithmeticException e) {
    System.out.println(e); // вывести исключение, созданное в блоке try
...

Ниже приводится демонстрация использования класса в коде

public class Train02 {
    public static void main(String[] args) {
        // создать екземпляр класса
        QuadraticEquation qE = new QuadraticEquation(1,1,1);
        qE.Solution(); // вызвать метод, решающий уравнение
        System.out.println("-------------------------");

        // создать другой екземпляр класса
        QuadraticEquation qE2 = new QuadraticEquation(0,3,5);
        qE2.Solution();
        System.out.println("-------------------------");

        QuadraticEquation qE3 = new QuadraticEquation(2,3,-5);
        qE3.Solution();
    }
}

Результат выполнения программы следующий:

java.lang.ArithmeticException: Уравнение не имеет корней.
-------------------------
java.lang.ArithmeticException: Деление на 0.
-------------------------
x1 = -2.5
x2 = 1.0

 

3. Какие типы запрещено использовать для генерирования исключений оператором throw?

Для генерирования исключений оператором throw запрещено использовать:

  • примитивные типы (например int, char);
  • классы, за исключением классов унаследованных от класса Throwable. Например, запрещено использовать класс String или другие классы.

 



4. Каким образом создать собственный класс исключения? Пример

Чтобы создать собственный класс исключения нужно, чтобы этот класс был унаследован от класса Exception. После того, как класс унаследован от класса Exception он уже есть частью системы исключений Java и его можно использовать как другие классы исключений (например ArithmeticException, ArrayIndexOfBoundsException и прочее).

Более подробно об использовании класса Exception и других классов описывается в теме:

  • Классы Java для обработки исключительных ситуаций. Примеры использования.

Если класс унаследован от класса Exception, то не обязательно даже реализовывать некоторые дополнительные операции в этом классе. В любом случае, исключение, которое соответствует этому классу, будет корректно перехватываться в блоке catch.

Класс Exception не содержит методов. Однако, этот класс есть унаследованным от класса Throwable. В классе Throwable есть доступными ряд методов, которые можно переопределить в собственном классе исключения.

Пример. С целью демонстрации объявляется класс NegativeNumberException. В нашем случае этот класс представляет собой исключение, которое генерируется в случае, когда число есть отрицательным. В классе объявляются:

  • внутренняя переменная value. Эта переменная есть необязательной и вводится с целью демонстрации;
  • конструктор, который есть необязательным;
  • метод toString(), переопределяющий одноименный метод класса Throwable. Этот метод выводит соответствующее сообщение.
// Объявить класс, который есть производным от класса Exception
// Данный класс есть частью системы исключений Java
class NegativeNumberException extends Exception {
    private double value;

    // некоторый конструктор класса
    NegativeNumberException(double _value) {
        value = _value;
    }

    // переопределенный метод toString() класса Throwable,
    // этот метод выводит информацию об исключении типа NegativeNumberException
    public String toString() {
        String msg = "Exception: " + value + " is a negative number!!!";
        return msg;
    }
}

public class Train04 {
    public static void main(String[] args) {
        // демонстрируется генерирование исключения типа NegativeNumberException
        double value;

        try {
            value = -5; // отрицательное число

            // если отрицательное значение,
            // то сгенерировать исключение типа NegativeNumberException
            if (value<0)
                throw new NegativeNumberException(value);
        }
        catch (NegativeNumberException e) {
            // вывести информацию об исключении
            // вызывается метод toString() класса NegativeNumberException
            System.out.println(e);
        }
    }
}

В вышеприведенном примере после объявления

class NegativeNumberException extends Exception {
    // ...
}

класс NegativeNumberException становится составной частью иерархии классов исключений Java. Поэтому можно его использовать в блоке catch конструкции try…catch.

В функции main() специально генерируется исключение типа NegativeNumberException в строке

...
if (value<0)
    throw new NegativeNumberException(value);
...

В результате программа переходит в блок catch, в котором выводится информация об исключении

...
catch (NegativeNumberException e) {
    System.out.println(e);
}
...

Фактически, вызывается метод toString() класса NegativeNumberException. Если бы метод toString() не был переопределен в классе NegativeNumberException, тогда был бы вызван метод toString() класса Throwable.

Результат выполнения программы

Exception: -5.0 is a negative number!!!

 

5. Какое назначение ключевого слова throws? Общая форма

Оператор throws используется в объявлении метода для того, чтобы сообщить вызывающий код о том, что данный метод может генерировать исключение, которое он не обрабатывает. Это касается всех исключений кроме:

  • классов Error и RuntimeException;
  • любых подклассов, которые унаследованы от классов Error и RuntimeException.

Общая форма использования оператора throws в методе имеет вид

type MethodName(parameters) throws exceptions_list {
    // ...
}

здесь

  • type – тип, который возвращает метод MethodName();
  • MethodName – имя метода;
  • parameters – параметры метода;
  • exception_list – перечень типов (классов) исключений разделенных запятой. Это есть перечень исключений, которые могут быть сгенерированы в методе MethodName().


 

6. Пример использования оператора throws для метода, который генерирует исключение

В примере объявляется класс NegativeNumberException производный от класса Exception. Этот класс есть классом исключения.

Также объявляется класс DemoThrows, который содержит метод SumItems(), способный вызвать исключение типа NegativeNumberException.

Программный код классов следующий

// Объявить класс, который есть производным от класса Exception
// После этого данный класс есть частью системы исключений Java
class NegativeNumberException extends Exception {
    private double value;

    // конструктор класса
    NegativeNumberException(double _value) {
        value = _value;
    }

    // переопределенный метод toString() класса Throwable,
    // этот метод виводит информацию об исключении типа NegativeNumberException
    public String toString() {
        String msg = "Exception: " + value + " is a negative number!!!";
        return msg;
    }
}

// демонстрация исключения
class DemoThrows {
    int SumItems(int A[]) throws NegativeNumberException {
        int i, sum=0;
        for (i=0; i<10; i++) {
            // если индекс за пределами массива, то сгенерировать исключение
            if (i>A.length)
                throw new ArrayIndexOutOfBoundsException("Индекс за пределами массива.");
            if (A[i]<0)
                throw new NegativeNumberException((double)A[i]);
            sum += A[i];
        }
        return sum;
    }
}

public class Train04 {
    public static void main(String[] args) {
        // вызов метода SumItems из класса DemoThrows
        int M[] = { 1, -2, 3, 4, 5, 6, 7 };
        DemoThrows dt = new DemoThrows(); // создать екземпляр класса DemoThrows
        int summ=0;

        try {
            // вызвать метод, в котором генерируется
            // исключение NegativeNumberException
            summ = dt.SumItems(M);
        }
        catch (NegativeNumberException e) {
            System.out.println("Отрицательное число: "+e);
        }
        catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Перехвачено исключение: " + e);
        }
        finally {
            System.out.println("Summ = " + summ);
        }
    }
}

В методе может возникнуть исключительная ситуация, которая вызовет исключение типа NegativeNumberException. Поэтому в объявлении метода присутствует ключевое слово throws с именем исключения

...
int SumItems(int A[]) throws NegativeNumberException {
    ...
}
...

Результат работы программы

Отрицательное число: Exception: -2.0 is a negative number!!!
Summ = 0

 


Связанные темы

  • Исключения. Исключительная ситуация. Ключевые слова try, catch, finally. Примеры

 


Как сгенерировать исключение JavaПредположим, что с вашей программой случилось нечто ужасное. У вас есть метод readData(), считывающий данные из файла, в заголовке которого указано следующиее:

Content-length: 1024

Однако посе воода 733 символов файл окончился. Вы считаете эту ситуацию настолько ненормальной, что решаете генерировать исключение. Теперь необходимо решить, какого типа должно быть исключение. Нам подходит одна из разновидностей класса IOException. Просматривая документацию, вы обнаруживайте описание исключения EOFException: «Сигнализирует о том, что во время ввода данных неожиданно обнаружен признак конца файла EOF». Отлично. Это исключение можно создать двумя способами:

throw new EOFException();

или, если вам так больше нравится:

EOFException e = new EOFException();

throw e;

Итак, для решения задачи нужно написать следующий фрагмент кода:

String readData(Scanner in) throws EOFException {

....

while(...) {

if(!in.hasNext()) {

if(n &lt; len)

throw new EOFException;

}

...

}

return s;

}

В классе EOFException есть второй конструктор, получающий в качестве параметра строку. Его можно использовать для более подробного описания исключения.

String gripe = «Content-length: » + len», Received: +n;

throw new EOFException(gripe);

Задача облегчается, если один из существующих классов исключений подходит для вашей цели. В этом случае нужно сделать следующее.

  1. Найти подходящий класс.
  2. Создать экземпляр этого класса.
  3. Генерировать исключение.

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

У вас проблемы с блоком питания ноутбука? Советуем  купить блок питания для ноутбука на сайте darrom.com.ua. Магазин Darrom.com.ua это место где вы можете купить оригинальные блоки питания по очень доступным ценам.

Понравилась статья? Поделить с друзьями:
  • Как сканировать реестр на наличие ошибок windows 10
  • Как связаны речевые ошибки и коммуникативные неудачи
  • Как сканировать компьютер на наличие ошибок
  • Как свести влияние систематических ошибок к минимуму
  • Как сканировать диск на ошибки windows 10