让构造函数抛出异常是一个好习惯吗?
例如我有一个类 Person
我有 age
作为其唯一属性。现在
我提供的类(class)为
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;
}
}
最佳答案
在构造函数中抛出异常并不是一个坏习惯。事实上,这是构造函数指示存在问题的唯一合理方式;例如参数无效。
我还认为,抛出已检查异常是可以的1,假设已检查异常已 1) 已声明,2) 特定于您所报告的问题,并且3) 期望调用者处理此检查异常是合理的2。
但是,显式声明或抛出 java.lang.Exception
几乎总是不好的做法。
您应该选择与已发生的异常情况相匹配的异常类。如果抛出Exception
,调用者很难将此异常与任何其他可能的已声明和未声明的异常分开。这使得错误恢复变得困难,并且如果调用者选择传播异常,问题就会蔓延。
1 - 有些人可能不同意,但在我看来,这种情况与在方法中抛出异常的情况没有实质性区别。标准检查与未检查建议同样适用于这两种情况。
2 - 例如,如果您尝试打开不存在的文件,现有的 FileInputStream 构造函数将抛出 FileNotFoundException 。假设 FileNotFoundException
是一个已检查异常3 是合理的,那么构造函数就是抛出该异常的最合适的地方。如果我们在第一次(例如)进行 read
或 write
调用时抛出 FileNotFoundException
,则可能会使应用程序逻辑变得更加复杂.
3 - 鉴于这是检查异常的激励示例之一,如果您不接受这一点,那么您基本上是在说所有异常都应该未经检查。如果您要使用 Java,那是不切实际的。
有人建议使用 assert
来检查参数。这样做的问题是可以通过 JVM 命令行设置打开和关闭断言检查。使用断言来检查内部不变量是可以的,但是使用它们来实现 javadoc 中指定的参数检查并不是一个好主意...因为这意味着您的方法只有在启用断言检查时才会严格实现规范。
assert 的第二个问题是,如果断言失败,则会抛出 AssertionError
。人们普遍认为, try catch Error
及其任何子类型是一个坏主意。但无论如何,您仍然会抛出异常,尽管是以间接的方式。
关于java - 让构造函数抛出异常是个好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55831045/