让构造函数抛出异常是一种好习惯吗? [英] Is it good practice to make the constructor throw an exception?
问题描述
让构造函数抛出异常是个好习惯吗?例如,我有一个类 Person
并且我有 age
作为它的唯一属性.现在我将课程提供为
Is it a good practice to make the constructor throw an exception?
For example I have a class Person
and I have age
as its only attribute. Now
I provide the class as
class Person{
int age;
Person(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
public void setAge(int age) throws Exception{
if (age<0)
throw new Exception("invalid age");
this.age = age;
}
}
推荐答案
在构造函数中抛出异常是一种不错的做法.事实上,这是构造函数指示存在问题的唯一合理方式;例如参数无效.
Throwing exceptions in a constructor is not bad practice. In fact, it is the only reasonable way for a constructor to indicate that there is a problem; e.g. that the parameters are invalid.
我也认为抛出checked异常是可以的1,假设checked异常是1)声明的,2)特定于你报告的问题,并且3) 期望调用者处理这个2的检查异常是合理的.
I also think that throwing checked exceptions can be OK1, assuming that the checked exception is 1) declared, 2) specific to the problem you are reporting, and 3) it is reasonable to expect the caller to deal with a checked exception for this2.
然而,明确声明或抛出 java.lang.Exception
几乎总是不好的做法.
However explicitly declaring or throwing java.lang.Exception
is almost always bad practice.
您应该选择一个与发生的异常条件相匹配的异常类.如果您抛出Exception
,调用者很难将这个异常与任何数量的其他可能的已声明和未声明的异常区分开来.这使得错误恢复变得困难,如果调用者选择传播异常,问题就会蔓延.
You should pick an exception class that matches the exceptional condition that has occurred. If you throw Exception
it is difficult for the caller to separate this exception from any number of other possible declared and undeclared exceptions. This makes error recovery difficult, and if the caller chooses to propagate the Exception, the problem just spreads.
1 - 有些人可能不同意,但 IMO 在这种情况下与在方法中抛出异常的情况没有实质性区别.标准的checked vs unchecked 建议同样适用于这两种情况.
2 - 例如,如果您尝试打开不存在的文件,现有的 FileInputStream
构造函数将抛出 FileNotFoundException
.假设 FileNotFoundException
成为受检异常3 是合理的,那么构造函数是抛出该异常最合适的地方.如果我们在第一次(比如)调用 read
或 write
时抛出 FileNotFoundException
,这可能会使应用程序逻辑更加复杂.
3 - 鉴于这是检查异常的激励示例之一,如果您不接受这一点,您基本上是在说所有异常都应该是未检查的.这不切实际……如果您打算使用 Java.
1 - Some people may disagree, but IMO there is no substantive difference between this case and the case of throwing exceptions in methods. The standard checked vs unchecked advice applies equally to both cases.
2 - For example, the existing FileInputStream
constructors will throw FileNotFoundException
if you try to open a file that does not exist. Assuming that it is reasonable for FileNotFoundException
to be a checked exception3, then the constructor is the most appropriate place for that exception to be thrown. If we threw the FileNotFoundException
the first time that (say) a read
or write
call was made, that is liable to make application logic more complicated.
3 - Given that this is one of the motivating examples for checked exceptions, if you don't accept this you are basically saying that all exceptions should be unchecked. That is not practical ... if you are going to use Java.
有人建议使用 assert
来检查参数.这样做的问题是可以通过 JVM 命令行设置打开和关闭对 assert
断言的检查.使用断言来检查内部不变量是可以的,但是使用它们来实现在你的 javadoc 中指定的参数检查并不是一个好主意......因为这意味着你的方法只会在启用断言检查时严格实现规范.
Someone suggested using assert
for checking arguments. The problem with this is that checking of assert
assertions can be turned on and off via a JVM command-line setting. Using assertions to check internal invariants is OK, but using them to implement argument checking that is specified in your javadoc is not a good idea ... because it means your method will only strictly implement the specification when assertion checking is enabled.
assert
的第二个问题是,如果一个断言失败,那么 AssertionError
将被抛出,而人们普遍认为这是一个坏主意 尝试捕获 Error
及其任何子类型.
The second problem with assert
is that if an assertion fails, then AssertionError
will be thrown, and received wisdom is that it is a bad idea to attempt to catch Error
and any of its subtypes.
这篇关于让构造函数抛出异常是一种好习惯吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!