2011-06-12 66 views
4

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

1.By使用try块和追赶的处理异常和:

如果检查异常的方法抛出,它必须在以下三种方式之一进行处理使用try块与它

2.By处理,并在处理程序捕获异常,但抛出 另一个异常要么是未经检查或声明其throws子句中

3.By通过声明 在抛出其方法头

我清楚地理解,第一和第三,但第二让我很多混乱的子句它明确地允许例外它的调用者的传播。我的担忧是:

- 即使我不抛出任何其他未经检查的异常仍然正常,那么为什么我们不得不在这里抛出另一个异常?

- 为什么我们必须在throws子句中重新声明我们已经捕获的异常?我认为这是经理人完成的。

感谢大家。

回答

3

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

- 它仍然是正常的,即使我不扔任何其他unchecked异常,所以 我们为什么在这里抛出另一个 异常?

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

- 为什么做,我们必须重新申报,我们已经捕捉到的异常,在 throws子句?我认为这是经过 处理程序。

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

+0

哦,我明白了。谢谢你的解释。 – 2011-06-12 01:26:05

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); 
     } 
    } 
} 
2

您可能想要执行此操作s来捕获一个检查的异常,并抛出另一种异常的异常。也许你想抛出你自己的例外,而不是一个不同的例外。

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(); 
    } 
} 
+0

你的例子就是我想要的。非常感谢你。 – 2011-06-12 02:13:00

0

通过使用try块和追赶的处理程序 例外,但抛出 另一个异常要么是 选中或宣布其throws子句 。

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

  • 结束语中的try-catch-finally块。
  • 声明方法抛出(使用抛出)异常的方法来处理的方法。

- 它仍然是正常的,即使我不扔任何其他unchecked异常,所以 我们为什么在这里抛出另一个 异常?

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

- 为什么做,我们必须重新申报,我们已经捕捉到的异常,在 throws子句?我认为这是经过 处理程序。

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

你必须去在这个Jon Skeet的帖子:Sheer Evil: Rethrowing exceptions in Java

记住,你永远不会被迫处理unchecked异常,编译器会强迫你刚刚赶上检查之一。

+0

在我看来,由于异常被捕获,它不会再传播给方法调用者,为什么调用者需要担心这种异常的发生? – 2011-06-12 01:46:03

+0

@Hung Tran:只有在这种情况下,如果发生的异常与catch子句中的异常不匹配。请记住,最佳做法是始终抓住特定的例外情况。 – 2011-06-12 01:48:45

+0

明白了,我只是误解了你的帖子,你想引用意外的异常不匹配的情况。我同意你的意见,作者提到增加更多的信息,以防我们在catch block中使用更普通的异常。感谢您的建议。 – 2011-06-12 02:06:32

1

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

其次,你不必这样做。这只是三种选择之一。

你为什么要那样做?通常这是在应用程序层之间完成的。例如,Hibernate捕获SQLException并将它们作为未经检查的HibernateException重新抛出,以便调用Hibernate方法的代码不必受SQLException的try/catch影响。另一种选择是将低级异常转换为可以在堆栈中处理的一些业务逻辑异常。这允许将业务逻辑与低级实施细节更好地隔离。