Thinking in Java中有一个练习:
使用可能的构造函数创建一个名为 FailingConstructor 的类 在施工过程中途失败并抛出异常。 在 main()中,编写能够正确防范此故障的代码。
这是我的解决方案:
class E1 extends Exception {
private FailingConstructor f;
E1(FailingConstructor f) { this.f = f; }
FailingConstructor getF() { return f; }
}
class FailingConstructor {
private Integer value;
FailingConstructor(int i) throws E1 {
if (i < 0) throw new E1(this);
value = i;
}
void set(int value) { this.value = value; }
public String toString() { return value.toString(); }
}
public class Program {
public static void main(String[] args) {
try {
FailingConstructor f2 = new FailingConstructor(-11);
} catch (E1 e) {
e.getF().set(0);
System.out.println(e.getF());
}
}
}
请告诉我,这是正确的运动解决方案吗?解决方案我发现(here)看起来很奇怪而且不合逻辑,我认为我的解决方案比这更好。
答案 0 :(得分:6)
将半构造实例的引用传递给异常的构造函数对我来说似乎是一个坏主意。
并且在catch子句中改变该实例是没有用的,因为在执行了catch子句之后,你的代码无论如何也都没有对该实例的引用。
catch子句应该报告发生了异常(打印错误消息或堆栈跟踪),如果适用则抛出不同的异常,或者 - 如果properly guards against this failure
意味着必须确保成功创建实例 - 创建FailingConstructor
的新实例,其创建保证不会抛出异常。如果选择最后一种方法,则应在FailingConstructor
块之前声明try
变量,以使其在try-catch块之后保留在范围内。
public class Program {
public static void main(String[] args) {
FailingConstructor f2 = null;
try {
f2 = new FailingConstructor(-11);
} catch (E1 e) {
f2 = new FailingConstructor(); // one way to recover from the exception
// is to use a different constructor
// that doesn't throw an exception
}
// now you can access f2
}
}
答案 1 :(得分:2)
通过throw new E1(this)
泄漏对部分构造的实例的引用是不明智的。
它允许你调用e.getF().set(-1)
,然后使用实例 - 这正是抛出异常以防范。
抛出异常没有问题 - 问题是它构造的FailingConstructor
的引用。删除它(和getF()
方法等),没关系。