无参数构造函数抛出一个不可能的异常或者有一个空的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,这可能会使库用户更加困惑,他们可能觉得他们必须在不需要时阅读自定义异常。
答案 0 :(得分:13)
NumberFormatException
是RuntimeException
,因此您无需在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所说,使用断言是向前迈进的一步,但这个解决方案有两个缺点:
所以我推荐给@yshavit提案。