Java 这是正确的练习方法吗?

Java 这是正确的练习方法吗?,java,exception,Java,Exception,有一个来自Java思考的练习: 创建一个名为FailingConstructor的类,其构造函数可能 在构建过程中中途失败并引发异常。 在main()中,编写正确防范此故障的代码 这是我的解决方案: class E1 extends Exception { private FailingConstructor f; E1(FailingConstructor f) { this.f = f; } FailingConstructor getF() { return f;

有一个来自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());
        }
    }
}
类E1扩展了异常{ 私人失败; E1(失败构造函数f){this.f=f;} FailingConstructor getF(){return f;} } 类失败构造函数{ 私有整数值; 失败构造函数(int i)抛出E1{ 如果(i<0)抛出新的E1(此); 值=i; } 无效集(int值){this.value=value;} 公共字符串toString(){返回值.toString();} } 公共课程{ 公共静态void main(字符串[]args){ 试一试{ FailingConstructor f2=新的FailingConstructor(-11); }渔获物(E1 e){ e、 getF().set(0); System.out.println(e.getF()); } } }
你能告诉我,这是正确的运动方案吗?我发现的解决方案()看起来很奇怪,不合逻辑,我认为我的解决方案比这更好。

将半构造实例的引用传递给异常的构造函数对我来说似乎是个坏主意

在catch子句中对该实例进行变异没有任何意义,因为在执行catch子句之后,您的代码无论如何都不会引用该实例

catch子句应该报告发生了异常(打印错误消息或堆栈跟踪),如果适用,则引发不同的异常,或者-如果
正确防范此故障
意味着必须确保成功创建实例-创建
故障构造函数
的新实例,该实例的创建保证不会引发异常。如果选择最后一种方法,则应在
try
块之前声明
FailingConstructor
变量,以便它在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
    }
}

通过抛出新E1(this)泄漏对部分构造实例的引用是不明智的

它允许您调用
e.getF().set(-1)
,然后使用实例——这正是抛出异常所要防止的


抛出异常没有问题-问题是引用了构造异常的
FailingConstructor
。删除这个(以及
getF()
方法等),就可以了。

这两个方法看起来都不错。在您的解决方案中,当您实现的验证失败时,将引发一个自定义异常。在另一个示例中,将引发ArrayIndexOutOfBoundsException,因为他们试图在包含两个元素的数组中存储第三个元素是处理该异常的正确方法。如果构造函数中存在由于异常而永远不会调用的其他初始化语句,则对象可能处于未定义/意外状态。此外,
f2
仍然为空,因为赋值没有发生。我宁愿用正确的值创建一个新实例,而不是重用失败的实例。通过
newe1(this)
泄漏对部分构造实例的引用是一个糟糕的主意。毕竟,它允许您调用
e.getF().set(-1)
,然后使用实例——这正是抛出异常所要防止的;因此,也许codereview.stackexchange.com会是这个请求的更好的地方。我们在这里帮助解决问题,我们不做代码审查。另一方面,Eran指出了代码中的一些问题;所以我想。。。很公平。您确定在try块之前声明变量是个好主意吗?构造函数可以抛出未选中的exception@luckystrrrike如果构造函数抛出异常且变量未初始化,则该变量将保持null(假设在声明时将其设置为null)。如果你想在try块之外访问它,你必须在try块之前声明它。但是IDE不允许这样做——它说的是“未处理的异常”。在第一条评论中,我的意思是“未处理”@luckystrrike你是什么意思?您从哪里获得未处理的异常?你删除了catch子句吗?@LuckyStrrike看我添加的示例这是一个学习示例,你可以在创建后设置任何值,但基本条件是不允许使用负值创建实例,对吧?但我的观点是,通过调用
e.getF().set(-1)
,你可以使用负值创建实例。