Как создать собственные исключения в Python?
Как создать новое исключение, отличное от стандартных типов?
Я пытаюсь создать собственное исключение в Java, используя следующий код:
public class InvalidBankFeeAmountException extends Exception{
public InvalidBankFeeAmountException(String message){
super(message);
}
}
Однако компилятор выдает предупреждение для InvalidBankFeeAmountException
, указанного в первой строке. Как можно решить эту проблему и правильно реализовать пользовательское исключение?
5 ответ(ов)
Чтобы создать новое исключение в Java, вам нужно создать новый класс и наследовать его от класса Exception
.
Если вы хотите создать неограниченное (unchecked) исключение, вам нужно наследоваться от класса RuntimeException
.
Примечание: Проверяемые (checked) исключения требуют, чтобы вы заключали их в блок try
/catch
или добавляли throws
в объявление метода (например, IOException
). Непроверяемые (unchecked) исключения могут возникать так же, как и проверяемые исключения, но вам не обязательно их явно обрабатывать (например, IndexOutOfBoundsException
).
Пример:
public class MyNewException extends RuntimeException {
public MyNewException(){
super();
}
public MyNewException(String message){
super(message);
}
}
Используя этот код, вы сможете создать собственное исключение, которое можно будет выбрасывать в случае возникновения определенных условий в вашем приложении.
Просто расширьте либо
Exception
, если вы хотите, чтобы ваше исключение было проверяемым (т.е. обязательно указывалось в секции throws)RuntimeException
, если вы хотите, чтобы ваше исключение было непроверяемым.
Не переусердствуйте с исключениями, особенно с проверяемыми. Рекомендую ознакомиться с главой 9 книги Джошуа Блоха "Effective Java", в частности с пунктом 60 (Предпочитайте использование стандартных исключений). Он также советует использовать проверяемые исключения для ситуаций, с которыми можно справиться, использовать непроверяемые исключения (RuntimeExceptions) для ошибок программирования и избегать ненужного использования проверяемых исключений.
Если при возникновении ошибки программирования выбрасывается исключение InvalidBankAccount, вероятно, вам следует просто выбросить стандартное непроверяемое исключение IllegalStateException вместо этого. Это позволит избежать необходимости объявлять serialVersionUID.
Обратите внимание на следующий ресурс:
http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html?page=1
На странице 2 приведён пример кода:
public class DuplicateUsernameException
extends Exception {
public DuplicateUsernameException
(String username){....}
public String requestedUsername(){...}
public String[] availableNames(){...}
}
В этом примере показано, как создать пользовательское исключение DuplicateUsernameException
, которое наследуется от класса Exception
. Как правило, создание собственных исключений имеет смысл в следующих случаях:
- Специфика проблемы: Если стандартные исключения не могут адекватно описать проблему, с которой вы столкнулись, например, дублирование имени пользователя.
- Информативность: Пользовательские исключения могут содержать дополнительные метаданные, такие как имя пользователя, что делает обработку ошибок более информативной.
- Упрощение отладки: Когда вы создаёте собственные исключения, это облегчает понимание того, что именно пошло не так, и упрощает отпуск ошибок.
Таким образом, следуя данным рекомендациям, вы сможете создать более чистый и понятный код, улучшая обработку ошибок в вашем приложении.
Ваш код содержит пользовательское исключение NotProperNameException
, которое используется для проверки корректности имени, введенного пользователем. Исключение выбрасывается, если имя не содержит только строчные буквы от 'a' до 'z'.
Однако в самом методе containsAlphabet
есть потенциальная ошибка: проверка имени происходит после того, как мы уже пытаемся проверить содержание букв, но это приводит к NullPointerException
, если значение name
равно null
.
Вот как можно исправить код, чтобы избежать ошибки и улучшить читаемость:
import java.util.Scanner;
class NotProperNameException extends Exception {
NotProperNameException(String msg) {
super(msg);
}
}
public class CustomCheckedException {
private String name;
private int age;
public static boolean containsAlphabet(String name) {
if (name == null) return false; // Добавлено условие для проверки на null
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (!(ch >= 'a' && ch <= 'z')) {
return false;
}
}
return true;
}
public CustomCheckedException(String name, int age) throws NotProperNameException {
if (!containsAlphabet(name)) {
String msg = "Некорректное имя (должно содержать только символы от a до z (все маленькие))";
throw new NotProperNameException(msg);
}
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Имя студента: " + this.name);
System.out.println("Возраст студента: " + this.age);
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Введите имя человека: ");
String name = sc.next();
System.out.println("Введите возраст человека: ");
int age = sc.nextInt();
try {
CustomCheckedException obj = new CustomCheckedException(name, age);
obj.display();
} catch (NotProperNameException e) {
System.out.println("Ошибка: " + e.getMessage());
} finally {
sc.close(); // Закрываем Scanner для освобождения ресурсов
}
}
}
Теперь, если name
равно null
, метод containsAlphabet
вернет false
, и исключение будет корректно выброшено без возникновения NullPointerException
. Также добавлен блок try-catch
в методе main
для обработки исключений и вывода соответствующего сообщения об ошибке.
Как проверить, что в JUnit-тестах выбрасывается определенное исключение?
Можно ли перехватить несколько исключений Java в одном блоке catch?
Mockito: Тестирование void метода, который выбрасывает исключение
Java - MySQL: Не разрешено извлечение открытого ключа (Public Key Retrieval)
Почему исключения SpyJMSExceptions все еще возникают после переработки клиентского соединения JBoss с удаленными очередями?