Java无参数构造函数:抛出不可能的异常,或者有空的catch块?

ano*_*mal 4 java constructor exception

无参数构造函数抛出一个不可能的异常或者有一个空的catch块是否更好?假设我有一个这样的课程.

public class Foo {
    private int num;
    private String numString;

    public Foo() throws NumberFormatException {
        setNum("1");
    }

    public void setNum(String s) throws NumberFormatException {
        // In reality, complex code goes here
        num = Integer.parseInt(s);
        numString = s;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器强制构造函数抛出NumberFormatException(这将永远不会发生)或具有try/catch块.但是,有一个空的捕获块是否正确,这通常是不受欢迎的?

public Foo() {
    try {
        setNum("1");
    } 
    catch (NumberFormatException e) { }
}
Run Code Online (Sandbox Code Playgroud)

请注意,Foo将是一个库类,其他人会使用它,因此使用无参数构造函数抛出一个不可能的异常会令人困惑.另请注意,真正的异常是自定义异常,而不是NumberFormatException,这可能会使库用户更加困惑,他们可能觉得他们必须在不需要时阅读自定义异常.

ysh*_*vit 13

NumberFormatException是一个RuntimeException,所以你不需要在你的throws条款上列出- 只是假装它不在那里.这适用于方法和构造函数.

RuntimeException(包括RuntimeException其自身)的任何子类都是"未经检查的异常",这意味着编译器不会强制您在try/catch子句中检查它.相反,任何Exception不是子类的都RuntimeException被称为检查异常.

如果它一个检查过的异常(也就是说,不是它的子类RuntimeException),但是你确定你永远不会触发它,那么抓住它是安全的.而不是完全吞下它,最好将它包裹在一个未经检查的异常中.

try {
    thisCodeCanNeverThrowAnIOException();
}
catch (IOException e) {
    throw new AssertionError(e); // juuust in case!
}
Run Code Online (Sandbox Code Playgroud)

现在你的代码编译了,没有throws一个你永远不会被抛出的异常的子句,但是如果由于某些bug或未来的变化而导致该异常最终被抛出,则不会隐藏严重的错误.

(请注意那些阅读评论的人:我原来在代码示例中throw new RuntimeException(e),但是Stephen C和Peter Lawrey指出,在Java 1.4.2和更新版本中,AssertionError更好).

  • +1 - 我更喜欢抛出"AssertionError",它具有更具体的含义"这应该永远不会发生". (3认同)
  • @yshavit - 这已不再正确.从Java 7开始,`AssertError` DOES有一个带有Throwable原因的构造函数 - http://docs.oracle.com/javase/7/docs/api/java/lang/AssertionError.html#AssertionError(java.lang.字符串%20java.lang.Throwable) (2认同)
  • @yshavit从Java 1.4.2开始,AssertionError将Throwable作为一个参数,它成为了原因.http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/AssertionError.html#AssertionError%28java.lang.Object%29 (2认同)