抑制-捕获或抛出永远不会发生的异常?

6

假设我有一个方法中的以下代码行:

 String encodedString = URLEncoder.encode(foo, "utf-8");

这个方法会抛出一个 UnsupportedEncodingException 异常。那么哪个更好呢:

/** @throws UnsupportedEncodingException umm...never
 */
public void myMethod() throws UnsupportedEncodingException {
   ...
   String encodedString = URLEncoder.encode(foo, "utf-8");
   ...
}

(强制调用者自己捕获异常)或:
public void myMethod() {
   try {
     ...
     String encodedString = URLEncoder.encode(foo, "utf-8");
     ...
   catch(UnsupportedEncodingException e) {
      Logger.log("cosmic ray detected!");
   }

}

还有没有更优雅的方式来处理那些不可能发生的异常呢?

2个回答

18

永远不要说永远;)

在上面的例子中,您始终可以捕获异常然后抛出RuntimeException:

public void myMethod() {
   try {
      ...
      String encodedString = URLEncoder.encode(foo, "utf-8");
       ...
   } catch(UnsupportedEncodingException e) {
     throw new RuntimeException("This should not be possible",e);
   }

}

采用这种方法可以避免强制调用者捕获一个你99.999%肯定不会发生的异常,但在极少数情况下如果确实出现了异常,你仍然会得到一个异常,以便你能够追踪并快速解决问题。

希望对你有所帮助。


两个答案都很好,但我选择接受这个答案是因为RuntimeException的想法非常棒。也许在这里使用IllegalStateException会更合适... - Epaga
5
另一个可能性是throw new AssertionError("this cannot happen", ex)。 (说明:该代码行意味着在遇到不应该发生的异常情况时,会抛出一个包含错误信息和原始异常的断言异常。) - Stephen C
@StephenC,这个比Runtime好吗? - Line
是的。使用 catch (Exception e) 不会意外地捕获它。 - Stephen C

6
如果你可以几乎保证异常永远不会发生,那么最好将这个断言局限在最窄的范围内而不是让它传播,因为其他人可能没有查看文档就不知道这一点。
如果一个方法声明要抛出异常,那么应该有实际的情况需要抛出。如果几乎可以保证不会抛出异常,那么最好完全省略throws子句并简化你的API。
根据你的抽象级别抛出适当的异常总是正确的(《Effective Java 2nd Edition》第61项)。声明可能抛出某些东西,当可以保证永远不会发生时,会破坏这个设计指南。

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