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

时间:2012-05-05 04:25:26

标签: java exception constructor

无参数构造函数抛出一个不可能的异常或者有一个空的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;
    }
}

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

public Foo() {
    try {
        setNum("1");
    } 
    catch (NumberFormatException e) { }
}

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

4 个答案:

答案 0 :(得分:13)

NumberFormatExceptionRuntimeException,因此您无需在throws条款中列出它 - 只是假装它不在那里。这适用于方法和构造函数。

RuntimeException的任何子类(包括RuntimeException本身)都是“未经检查的异常”,这意味着编译器不会强制您在try / catch子句中检查它。相比之下,任何不是Exception子类的RuntimeException都被称为检查异常。

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

try {
    thisCodeCanNeverThrowAnIOException();
}
catch (IOException e) {
    throw new AssertionError(e); // juuust in case!
}

现在你的代码编译了,对于你从未期望抛出的异常没有throws子句,但如果由于某些错误或未来的更改而异常终止,则不会隐藏严重错误被抛出。

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

答案 1 :(得分:1)

因为s必须是数字,为什么不通过setNum()而不是当前字符串传递整数?一个整数总是可以解析为字符串。

答案 2 :(得分:1)

我想说这取决于你的商业关怀或个人编码风格,如果你选择抛出一个异常,它可能会更好地拥有一个拥有和包装的异常,如果你传入的参数不正确或没有意义你现在可以抛出异常。

无论抛出NumberFormatException,这都是一个正确的决定,你可以抓住它。它可能在您的图书馆班级,或来电者班级,或您不知道的地方。没有它,程序将会失效。

在您的情况下,您是否将无数字符串视为合法值,如果是,则您有责任将异常保留在包中。

答案 3 :(得分:0)

我会说:永远不要空挡块(无论如何)。正如@yshavit指出的那样,吞下可能的错误并不是一个好习惯。

正如@ stephen-c所说,使用断言是向前迈进的一步,但这个解决方案有两个缺点:

  1. 在“运营/生产”服务器上可能没有启用断言,所以你真正拥有的非常类似于空的catch块
  2. 如果它们在服务器上启用,执行这段代码时出现错误将证明您的应用程序中存在错误,只要它不会出现预期(“这应该永远不会发生”,但它发生!所以...)
  3. 所以我推荐给@yshavit提案。