我该如何编写自定义异常?

54

我怎样可以创建一个与预定义异常类型不同的新异常

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

它将显示第一行编写的InvalidBankFeeAmountException警告。


我自己创建了一个异常,如上所示。创建一个名为该特殊异常的类并扩展Exception。 但是,它有一个警告:可序列化类<该异常的名称>Exception没有声明一个静态的final serialVersionUID长字段。 我该怎么解决它? - Johanna
1
如果你不想的话,你不必担心那个警告。因为Exception类是可序列化的,所以它要求你为该类设置一个序列号。但是,由于这只是一个警告,我通常会忽略它。 - jjnguy
但是当我在main()方法中使用这个类作为类型时,会显示另一个警告:无法抛出InvalidBankFeeAmountException类型。 - Johanna
1
你是否声明它为“throws InvalidBankFeeAmountException”? - Michael Myers
你所遇到的错误让我认为你没有正确地扩展 Exception。 - jjnguy
5个回答

118
您只需要创建一个新的class,并使其 extend Exception 就可以了。
如果您想要一个未检查的 Exception,则需要extend RuntimeException注意:被检查的 Exception 是指需要您在方法声明上添加 'throws' 子句或者在 try/catch 块中处理它们(如 IOException)。未经检查的 Exceptions 可以像已检查的 Exceptions 一样被抛出,但您不需要以任何方式显式地处理它们(如 IndexOutOfBoundsException)。
例如:
public class MyNewException extends RuntimeException {

    public MyNewException(){
        super();
    }

    public MyNewException(String message){
        super(message);
    }
}

40
注:如果您使用的是Eclipse,则只需编写 'throw new <CustomName>Exception',然后使用自动修复(Ctrl + 1)。 这将为您创建一个扩展 Exception 并包含样板代码的新类。 - James Van Huis
5
我听说扩展RuntimeExceptions可能是不好的做法:如果客户端可以合理地预期从异常中恢复,将其设为已检查异常。如果客户端无法从异常中恢复,则将其设为未检查异常。 - AncientSwordRage
我刚刚读完其他答案,你已经解决了它,我需要在评论之前阅读比代码更多的内容。 - AncientSwordRage
5
我认为扩展 RuntimeException 并不是一种不好的做法。如果代码中没有到处都是检查异常,这确实会使你的代码更易于使用。 - jjnguy

33

只需扩展以下之一

  • Exception,如果您希望您的异常被检查(即:在 throws 子句中需要)
  • RuntimeException,如果您希望您的异常不被检查。

6
请勿过度使用异常,特别是已检查的异常。建议阅读Joshua Bloch的Effective Java第9章,尤其是他的第60条建议(支持使用标准异常)。他的建议包括将已检查的异常用于可以恢复的异常,将未检查的异常(RuntimeExceptions)用于编程错误,并避免不必要地使用已检查的异常。
如果在发现编程错误时抛出InvalidBankAccount异常,您可能只想抛出标准的未检查Java IllegalStateException异常。(这样可以巧妙地绕过声明serialVersionUID的需要。)

3
请看以下内容:

请查看:

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(){...}
}

同时提供了一套指南,说明何时以及为什么需要创建自己的异常。


0
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) {
      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){
      if(!containsAlphabet(name)&&name!=null) {
         String msg = "Improper name (Should contain only characters between a to z (all small))";
         NotProperNameException exName = new NotProperNameException(msg);
         throw exName;
      }
      this.name = name;
      this.age = age;
   }
   public void display(){
      System.out.println("Name of the Student: "+this.name );
      System.out.println("Age of the Student: "+this.age );
   }
   public static void main(String args[]) {
      Scanner sc= new Scanner(System.in);
      System.out.println("Enter the name of the person: ");
      String name = sc.next();
      System.out.println("Enter the age of the person: ");
      int age = sc.nextInt();
      CustomCheckedException obj = new CustomCheckedException(name, age);
      obj.display();
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接