Хотя имеющиеся в стандартной библиотеке классов Java классы исключений описывают большинство исключительных ситуаций, которые могут возникнуть при выполнении программы, все-таки иногда требуется создать свои собственные классы исключений со своей логикой.
Чтобы создать свой класс исключений, надо унаследовать его от класса Exception. Например, у нас есть класс, вычисляющий факториал, и нам надо выбрасывать специальное исключение, если число, передаваемое в метод, меньше 1:
import java.util.Scanner;
class Program{
public static void main(String[] args) throws Exception {
createPerson("Tom", -10);
}
static void createPerson(String name, int age){
try{
var person = new Person(name, age);
person.print();
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
}
}
class Person{
private String name;
private int age;
Person(String name, int age) throws Exception{
if(name.length() < 2) throw new Exception("Недостаточная длина имени: " + name.length());
if(age < 1 || age > 110) throw new Exception("Некорректный возраст: " + age);
this.name = name;
this.age = age;
}
void print(){ System.out.printf("Name: %s; Age: %d\n", name, age); }
}
В классе Person в конструкторе получаем имя и возраст пользователя и проверяем их на соответствие некоторым условиям. В частности, если длина имени меньше 2 символов или
возраст меньше 1 или больше 110, то выбрасываются исключения. В качестве типа генерируемого исключения применяется базовый класс Exception, в конструктор которого передается сообщение об ошибке:
Person(String name, int age) throws Exception{
if(name.length() < 2) throw new Exception("Недостаточная длина имени: " + name.length());
if(age < 1 || age > 110) throw new Exception("Некорректный возраст: " + age);
this.name = name;
this.age = age;
}
И поскольку конструктор сам не обрабатывает эти исключения, то в его объявлении с помощью оператора throws указываем компилятору, что конструктор генерирует исключения типа Exception.
В методе createPerson() собственно обрабатываем исключения при вызове конструктора и создании объекта Person:
try{
var person = new Person(name, age);
person.print();
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
Подобный подход вполне можно использовать. Но иногда удобнее использовать свои классы исключений. Например, в какой-то ситуации мы хотим обработать определенным образом только те исключения,
которые относятся к классу Person. Или выделить исключительные случаи и ошибки для класса Person в отдельные классы. Для этих целей мы можем сделать специальный класс PersonException:
class PersonException extends Exception{
PersonException(String message){
super(message);
}
}
По сути класс кроме пустого конструктора ничего не имеет, и то в конструкторе мы просто обращаемся к конструктору базового класса Exception, передавая в него строку с сообщением об ошибке. Но теперь мы можем изменить класс Person, чтобы он выбрасывал
исключение именно этого типа и соответственно в основной программе обрабатывать это исключение:
class Program{
public static void main(String[] args) throws Exception {
createPerson("Tom", -10);
createPerson("m", 20);
}
static void createPerson(String name, int age){
try{
var person = new Person(name, age);
person.print();
}
catch(PersonException ex){
System.out.println(ex.getMessage());
}
}
}
class PersonException extends Exception{
PersonException(String message){
super(message);
}
}
class Person{
private String name;
private int age;
Person(String name, int age) throws PersonException{
if(name.length() < 2) throw new PersonException("Недостаточная длина имени: " + name.length());
if(age > 1 || age > 110) throw new PersonException("Некорректный возраст: " + age);
this.name = name;
this.age = age;
}
void print(){ System.out.printf("Name: %s; Age: %d\n", name, age); }
}
Консольный вывод программы:
Некорректный возраст: -10 Недостаточная длина имени: 1
Но мы можем пойти дальше и создать для отдельных ситуаций свои типы исключений. Например:
class Program{
public static void main(String[] args) throws Exception {
createPerson("Tom", -10);
createPerson("m", 20);
}
static void createPerson(String name, int age){
try{
var person = new Person(name, age);
person.print();
}
catch(PersonNameException ex){
System.out.println("Ошибка в имени:");
System.out.println(ex.getMessage());
}
catch(PersonAgeException ex){
System.out.println("Ошибка в возрасте:");
System.out.println(ex.getMessage());
}
}
}
class PersonNameException extends Exception{
PersonNameException(String name, int minLength){
String message = "Недостаточная длина имени. Текущее значение: " + name + ". Минимальная длина имени: " + minLength;
super(message);
}
}
class PersonAgeException extends Exception{
PersonAgeException(int age, int minAge, int maxAge){
String message = "Некорректный возраст. Текущее значение: " + age +
". Минимальный возраст: " + minAge + ". Максимальный возраст: " + maxAge;
super(message);
}
}
class Person{
private String name;
private int age;
private static int nameMinLength = 2;
private static int minAge = 1;
private static int maxAge = 110;
Person(String name, int age) throws PersonNameException, PersonAgeException {
if(name.length() < nameMinLength) throw new PersonNameException(name, nameMinLength);
if(age < minAge || age > maxAge) throw new PersonAgeException(age, minAge, maxAge);
this.name = name;
this.age = age;
}
void print(){ System.out.printf("Name: %s; Age: %d\n", name, age); }
}
Здесь для ошибок имени определен тип PersonNameException, а для ошибок при указании возраста - тип PersonAgeException. Оба типа наследуются от Exception и
через конструктор получают данные об ошибке.
Конструктор класса Person генерирует исключения этих типов:
Person(String name, int age) throws PersonNameException, PersonAgeException {
А в методе createPerson() при создании объектов Person обрабатываем по отдельности оба этих вида исключений:
catch(PersonNameException ex){
System.out.println("Ошибка в имени:");
System.out.println(ex.getMessage());
}
catch(PersonAgeException ex){
System.out.println("Ошибка в возрасте:");
System.out.println(ex.getMessage());
}
В итоге мы получим следующий консольный вывод:
Ошибка в возрасте: Некорректный возраст. Текущее значение: -10. Минимальный возраст: 1. Максимальный возраст: 110 Ошибка в имени: Недостаточная длина имени. Текущее значение: m. Минимальная длина имени: 2