处理检查的异常

问题描述

| 我正在阅读《 Java SCJP证书程序员指南》这本书中的异常处理。作者写道:   如果在方法中引发了检查的异常,则必须以以下三种方式之一对其进行处理:      1.通过使用try块并在处理程序中捕获异常并对其进行处理      2.通过使用try块并在处理程序中捕获异常,但是抛出   另一个未经检查或在其throws子句中声明的异常      3通过明确声明允许异常传播给调用者   在其方法标题的throws子句中 我对第一个和第三个很清楚,但是第二个让我很困惑。我担心的是: -即使我没有抛出任何其他未经检查的异常,也还是可以的,那为什么我们还要在这里抛出另一个异常呢? -为什么我们必须在throws子句中重新声明捕获的异常?我认为处理程序已结束。 谢谢大家。     

解决方法

        该书仅列出了三个允许的选项。   -即使我没有抛出任何其他未经检查的异常,它也仍然可以,   那我们为什么还要扔另一个   这里有例外吗? 您可能想抛出另一个更具描述性的异常,例如添加更多信息。   -为什么我们必须重新声明已捕获的异常   引发子句?我认为这已经过去了   处理程序。 您不必重新声明。但是,如果检查了您要抛出的新异常,则必须在throws子句中声明它。实际上,即使选中,您刚刚捕获的异常也不需要声明。     ,        您可能想要执行此操作以捕获受检查的异常并引发另一种不同类型的受检查的异常。也许您想抛出自己的异常,而不是其他异常。
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();
    }
}
    ,        首先,您应该在throw子句中声明您抛出的异常,而不是假设捕获的异常引发的异常。 其次,您不必这样做。它只是三个选项之一。 为什么要这么做?通常,这是在应用程序层之间完成的。例如,Hibernate捕获SQLException,然后将其作为未经检查的HibernateException重新抛出,这样,调用Hibernate方法的代码就不必使用try / catching来污染SQLException。另一个选择是将低级异常转换为可以在堆栈中处理的某些业务逻辑异常。这样可以更好地将业务逻辑与底层实现细节隔离开。     ,        很好的问题,还有一个优秀的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);
        }
    }
}
    ,           通过使用try块并捕获   处理程序中的异常,但抛出   另一个例外是   未经检查或声明抛出   条款。 用Java处理异常可以通过两种方式完成: 将其包装在try-catch-finally块中。 声明方法(使用throws)引发方法调用者要处理的异常。   -即使我没有抛出任何其他未经检查的异常,它也仍然可以,   那我们为什么还要扔另一个   这里有例外吗? 引发另一个异常意味着要对其进行更多描述。同样,让方法的调用者知道此特定异常已生成。   -为什么我们必须重新声明已捕获的异常   引发子句?我认为这已经过去了   处理程序。 重新声明刚刚捕获在catch块中的异常是为了使此方法的调用者警惕此方法可能引发特定异常。因此,请做好准备。 您必须阅读此
Jon Skeet
的帖子:
Sheer Evil: Rethrowing exceptions in Java
请记住,您永远不会被迫处理未检查的异常,编译器会强迫您仅捕获已检查的异常。