3

我对在 Java 中创建 API 有设计层面的疑问。假设我有一个课程如下: -

class Test
{
  public final static String DEFAULT_ENCODING = "utf-8";

  public byte[] encodeIt(String input)
  {
    try {
      return input.getBytes(DEFAULT_ENCODING);
    } catch(UnsupportedEncodingException e) {
      // do something
    }
  }
}

我知道UnsupportedEncodingException永远不会出现,因为我使用静态字符串作为toBytes. encodeIt这样做是没有意义的,throws UnsupportedEncodingException因为我也不希望 API 用户期望并捕获该错误。

在这种情况下,最好的做法是有一个空的 catch 块吗?

4

6 回答 6

5

我做这样的事情:

public byte[] encodeIt(String input) {
    try {
        return input.getBytes(DEFAULT_ENCODING);
    }
    catch (UnsupportedEncodingException e) {
        throw new ShouldNeverHappenException(e);
        // or: throw new IllegalStateException(e);
    }
}

(当然,ShouldNeverHappenException 是运行时异常)。

这样,如果有人碰巧更改了常量值,或者添加了编码参数,该方法将很快失败,并且问题不会被忽视或隐藏在日志文件中。

于 2012-12-16T10:25:04.140 回答
5

有空的 catch 块是个坏主意。即使您的推理似乎是正确的,这种设计也会在某个阶段导致您无休止的调试和搜索,一旦异常开始发生并且您的代码正在吞噬它们。我会在这里将您的异常包装在 RuntimeException 中并抛出它。像这样:

public encodeIt(String input)
  {
    try {
      return input.getBytes(DEFAULT_ENCODING);
    catch(UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

这样,您的异常将不会保持隐藏,即使它发生,您的 API 用户也不必迎合它。

于 2012-12-16T10:26:57.697 回答
3

在这种情况下,最好的做法是有一个空的 catch 块吗?

我不觉得这是一个好主意,从来没有。空的 catch 块意味着可能会发生一些事情,而你永远不会知道。

不要抛出这个异常。抓住它并记录下来,这样你就可以检查你的假设,即它永远不会发生,但至少你会知道它是否永远不会发生。

于 2012-12-16T10:24:42.153 回答
2

我通常遵循此问题的其他答案概述的策略(例如将已检查的异常软化为RuntimeException)。然而,一个有趣的替代方法是使用断言:

public byte[] encodeIt(String input)
{
  try {
    return input.getBytes(DEFAULT_ENCODING);
  } catch(UnsupportedEncodingException e) {
    assert false;
    return null;
  }
}

当使用-eaJVM 标志启用断言时,此方法将抛出一个AssertionErrorif ever UnsupportedEncodingExceptionbeen throwed。一个烦恼是需要返回一个值(例如null),否则代码将无法编译。

所以也许以下是“更好的”:

public byte[] encodeIt(String input)
{
  try {
    return input.getBytes(DEFAULT_ENCODING);
  } catch(UnsupportedEncodingException e) {
    throw new AssertionError("Unexpected.", e);
  }
}

与投掷没有太大区别RuntimeExceptionAssertionError只是很好地自我记录。而且,作为 的子类Error,它代表了比Exception通常暗示的更根本的失败。没有机会让catch (Exception e)堆栈中更高位置的子句处理这件事(如果它曾经发生过)。

于 2012-12-16T11:06:57.987 回答
1

我认为最好的方法是避免检查异常。只需使用未选中的。然后,您将充分利用两个世界:如果确实发生错误,您将发出错误信号,并且您不会强迫 API 的用户处理异常。

于 2012-12-16T10:27:01.417 回答
0

如果您非常非常确定它永远不会发生,请留下一个空的 catch 块。但是为了练习,以防您以后更改代码,最好在发生异常时将其记录到控制台。

于 2012-12-16T10:24:44.700 回答