处理已检查的异常

时间:2011-06-12 01:16:15

标签: java exception-handling

我正在阅读“Java SCJP证书程序员指南”一书中的异常处理。作者写道:

  

如果方法中抛出了已检查的异常,则必须以下列三种方式之一处理:

     

1.使用try块并在处理程序中捕获异常并处理它

     

2.使用try块并在处理程序中捕获异常,但抛出   另一个例外是未选中在其throws子句中声明

     

3.明确允许通过声明将异常传播给其调用者   在其方法标题的throws子句中

我清楚地理解了第一个和第三个,但第二个让我很困惑。我担心的是:

- 即使我没有抛出任何其他未经检查的异常,它仍然没有问题,为什么我们不得不在这里抛出另一个例外?

- 为什么我们必须在throws子句中重新声明我们捕获的异常?我认为处理程序已经结束了。

感谢大家。

5 个答案:

答案 0 :(得分:3)

这本书只列出了三个允许的选项。

  

- 即使我没有抛出任何其他未经检查的异常,它仍然没有问题,   那么我们为什么要扔另一个呢?   这里有例外吗?

您可能想要引发另一个更具描述性的异常,例如添加更多信息。

  

- 为什么我们必须重新声明我们捕获的异常   抛出条款?我认为它已经结束了   处理程序。

您无需重新声明。但是如果检查了你抛出的新异常,那么你必须在throws子句中声明它。事实上,即使经过检查,您刚刚捕获的异常也不需要声明。

答案 1 :(得分:2)

您可能希望执行此操作以捕获已检查的异常并抛出另一种已检查的异常。也许你想抛出自己的例外而不是另一个例外。

public void doSomething() throws MyCheckedException {
    try {
        doSomethingThatThrowsSpecificCheckedException();
    } catch(SpecificCheckedException e) {
        throw new MyCheckedException();
    }
}

或者你可以抛出一个未经检查的异常(某些东西是或RuntimeException}。

public void doSomething() {
    try {
        doSomethingThatThrowsSpecificCheckedException();
    } catch(SpecificCheckedException e) {
        throw new RuntimeException();
    }
}

答案 2 :(得分:1)

很好的问题,一个优秀的java程序员应该深入了解。

所有这些都是为了遵守方法签名,该方法签名定义了方法与其调用者的契约,并且包括将要抛出的异常。

  • 选项1正在处理异常
  • 选项2不是处理异常,而是保持相同的合同
  • 选项3不处理例外并更改合同

选项2中模式的实现将是:

public interface Server {
    public void useServer() throws ServerException;
}

public class ExplodingClient {
    private Server server = new ServerImpl();
    public void doIt() throws ClientException {
        try {
            server.useServer();
        } catch (ServerException e) {
            // Our contract doesn't allow throwing ServerException,
            // so wrap it in an exception we are allowed by contract to throw
            throw new ClientException(e);
        }
    }
}


public class SilentClient {
    private Server server = new ServerImpl();
    public void doIt() {
        try {
            server.useServer();
        } catch (ServerException e) {
            // Our contract doesn't allow throwing any Exceptions,
            // so wrap it in a RuntimeException
            throw new RuntimeException(e);
        }
    }
}

答案 3 :(得分:1)

首先,你应该在throw子句中声明抛出的异常,而不是你捕获的异常,假设你抛出一个已检查的异常。

其次,你不必这样做。这只是三个选项中的一个。

你为什么这样做?通常这是在应用程序层之间完成的。例如,Hibernate捕获SQLExceptions并将它们重新抛出为未经检查的HibernateException,因此调用Hibernate方法的代码不必被SQLExceptions的try / catches污染。另一个选择是将低级异常转换为可以在堆栈中处理的某些业务逻辑异常。这样可以更好地将业务逻辑与低级实现细节隔离开来。

答案 4 :(得分:0)

  

通过使用try块并捕获   处理程序中的异常,但抛出   另一个例外是   未经检查或在其投掷中声明   条款。

在Java中处理异常可以通过两种方式完成:

  • 将它包装在try-catch-finally块中。
  • 声明方法抛出(使用throws)异常给要处理的方法的调用者。
  

- 即使我没有抛出任何其他未经检查的异常,它仍然没有问题,   那么我们为什么要扔另一个呢?   在这里例外?

抛出另一个异常意味着要更多地描述它。此外,让方法的调用者知道生成了这个特殊的异常。

  

- 为什么我们必须重新声明我们捕获的异常   抛出条款?我认为它已经结束了   处理程序。

重新声明您刚刚在catch块中捕获的异常是让此方法的调用者警告此方法可能会引发特定异常。所以要准备好处理它。

您必须查看此Jon Skeet的帖子:Sheer Evil: Rethrowing exceptions in Java

请记住,您永远不会被迫处理未经检查的异常,编译器会强制您抓住已检查的异常。