java 自定义业务异常_java 的自定义异常

3.2自定义异常

前面讨论了如何处理调用Java API的方法时产生的异常。根据需要,还可创建和使用自定义异常——自我构建表示错误的类。可创建全新异常,并将它们用于应用程序。

使用自定义异常有什么好处呢?为何要定义新异常类型?创建自定义异常是为了表示应用程序的一些错误类型,为代码可能发生的一个或多个问题提供新含义。可以显示代码多个位置之间的错误的相似性,也可区分代码运行时可能出现的相似问题的一个或多个错误,或给出应用程序中一组错误的特定含义。

例如,考虑任何类型的服务器。服务器的基本作用是处理与客户机的通信。若使用标准Java API(如java.io和java.net包中的类)来编写服务器,则可使编写的代码在多个位置抛IOException。 在设置服务器、等待客户机连接和获取通信流时,可抛出IOExceptions;在通信期间及试图断开连接时,也可抛出IOExceptions。简言之,服务器的各个部分都可能引发IOException。

对服务器而言,这些IOException意义不尽相同。虽然由同一异常类型表示,但与各个异常相关的业务含义存在差异,报告和恢复操作亦有不同。可以将一个异常集与服务器配置和启动问题关联,将另一个异常集与客户机通信的实际行动关联,将第三个异常集与服务器关闭任务关联。使用自定义异常,可采用对应用程序有意义的方式来灵活地表示错误。

创建和使用自定义异常并不难。遵循以下3个步骤即可。

3.2.1 定义异常类

一般要定义新类来表示自定义异常。多数情况下,只需创建已有异常类的子类。

1  public class CustomerExistsException extends Exception{

2    public CustomerExistsException(){}

3    public CustomerExistsException(String message){

4      super(message);

5    }

6  }

至少要继承Throwable或Throwable的子类。经常需要定义一个或多个构造函数,以在对象中存储错误消息。如第2-4行所示。在继承任何异常时,将自动继承Throwable类的一些标准特性,如:

●错误消息

●栈跟踪

●异常包装

若要在异常中添加附加信息,则可以为类添加一些变量和方法:

1  public class CustomerExistsException extends Exception{

2    private String customerName;

3    public CustomerExistsException(){}

4     public CustomerExistsException(String message){

5       super(message);

6     }

7     public CustomerExistsException(String message, String customer){

8       super(message);

9       customerName = customer;

10     }

11     public String getCustomerName(){

12       return customerName;

13     }

14  }

由本例可知,可修改CustomerExistsException类,以支持其他属性。例如,可将customerName字符串(引发异常的记录的客户名)与异常联系起来。

3.2.2 声明方法抛出自定义异常

这实际上是“处理或声明”规则的“声明”部分。为了使用自定义异常,必须通知调用代码的类:要准备处理这个异常类型。为此,声明一个或多个方法抛出异常:

public void insertCustomer(Customer c)throwsCustomerExistsException{

// The method stores customer information in the database.

// If the customer data already exists, the method creates

// and throws the CustomerExistsException.

}

3.2.3 找到故障点,新建异常并加上关键字throw

最后一步实际上是创建对象,并通过系统传送该对象。为此,需要了解代码将在方法的哪个位置出现故障。根据情况,可能要使用以下部分或所有条件,来指示代码中的故障点。

1.外部问题

●应用程序中产生的异常

●其他方法返回的故障代码

2.内部问题

●应用程序状态不一致

●应用程序中的处理问题

在本例中,当不能新建一个客户时会遇到一个故障场景。结果,创建一个异常来表示问题并抛出该问题。如下面的示例方法所示:

1  public void insertCustomer(Customer c)

2throws CustomerExistsException, SQLException {

3    String selectSql =

4      "SELECT * FROM Customer WHERE first_name=? AND last_name=?";

5    String insertSql = "INSERT INTO Customer VALUES(?, ?)";

6    try{

7      Connection conn = dbmsConnectionFactory.getConnection();

8      PreparedStatement selStmt = conn.prepareStatement(selectSql);

9      selectStmt.setString(1, c.getFirstName());

10      selectStmt.setString(2, c.getLastName());

11      ResultSet rs = selStmt.executeQuery();

12      if (rs.next()){

13        // In this case, the failure condition is produced if you

14        //  can already locate a metching record in the database.

15       throw new CustomerExistsException("Customer exists:" + c, c);

16      }

17      else{

18        PreparedStatement insStmt = conn.prepareStatement(insertSql);

19        insStmt.setString(1, c.getFirstName());

20        insStmt.setString(2, c.getLastName());

21        int status = insStmt.executeUpdate();

22      }

23   }

24   catch (SQLException exc){

Java关键字throw将这个新异常对象传给该方法的调用者。在执行完这3个步骤后,就创建了自定义异常。除非派生一个非检测异常类(如RuntimeException或Error),否则调用方法的任何对象随后将按照“处理或声明”规则解决该异常。

这引出了一个有趣的问题:在自定义异常时,应如何派生?必须在Throwable类层次结构中派生,否则将不能在应用程序中传播异常。另外,不能从Throwable直接派生。Throwable为两类主要问题(Exception和Error)提供行为基础,不能为这棵继承树定义新分支。一般也不要直接继承Error或其任何子类,因为自定义异常通常不符合错误标准(即适当应用程序不应试图捕获的严重问题)。

需要从Exception类层次结构中派生。一般地,应将自定义异常定义为故障状态更一般的异常类型的子类。例如,ServerConnectionException是java.io.IOException的子类,因为Server- Connec tionException是java.io.IOException的更具体类型。

如果定义的异常从RuntimeException树继承,是否属于正确的编码实践?若如此,就回避了异常机制,即使声明了异常,类也不必显式处理异常。

通过本例,可了解到如何创建基本的自定义异常。很多情况下,这可轻易地满足要求。自定义异常类(可能还有消息)经常是应用程序惟一需要的异常。有时,需要支持更高级的特性,在一些异常中,可能要用到两个属性:链表(chaining)和本地化(localization)。

posted on 2008-01-08 11:41 sunnywang 阅读(6291) 评论(0)  编辑 收藏 引用 所属分类: language-java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值