luckystrrrike luckystrrrike - 4 months ago 8
Java Question

Is this the correct exercise solution?

There is a exercise from Thinking in Java:


Create a class called FailingConstructor with a constructor that might
fail partway through the construction process and throw an exception.
In main(), write code that properly guards against this failure.


This is my solution:

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());
}
}
}


Could you please tell me, is this the correct exercise solution? Solution I found (here) looks rather strange and illogicaly and I think my solution is better than this.

Answer

Passing a reference of the half constructed instance to the constructor of the exception seems like a bad idea to me.

And mutating that instance in the catch clause serves no purpose, since after the catch clause is executed, your code will have no reference to that instance anyway.

The catch clause should either report that an exception occurred (print an error message or stack trace), throw a different exception if applicable or - if properly guards against this failure means that the successful creation of an instance must be ensured - create a new instance of FailingConstructor whose creation is guaranteed not to throw an exception. If you choose the last approach, you should declare the FailingConstructor variable before the try block, in order for it to remain in scope after the try-catch block.

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
    }
}
Comments