Java – Why don’t constructor return bool to indicate its success or failure without having to throw an exception

cjavaobject-orientedobjective c

Take C++ constructors for example, we know they don't return values. Why did Bjarne Stroustrup in the beginning decide not to allow constructor returning 'false' to indicate it fails, so that the run time system can destruct its constructed members just like throwing an exception? What are the concerns that make OO language designers decide not to do so? The "new" operator can therefore return "nullptr" if it see constructor returns false. For static objects (in .data/.bss area or on .stack) the compiler generated construction code can still detect and signal, abort or exit accordingly.

Consider the following two coding paradigms, using dynamic allocation as an example:

objp = new object; // constructor returns 'false', 'new' returns 'nullptr'.
if (objp != nullptr) {
    do_something(objp);
} else {
    error_handling();
}

compare to:

try {
    objp = new object; // object throw exception when construction failed
    do_something(objp);
} catch (const typedException &e) {
    error_handling();
}

If we need to encode the reason of construction failure, the latter using exception is of course more helpful as we can't use 'objp' to pass any information once construction failed. But if the reason is simple (say 'out of memory'), or when skipping error handling does no harm (do_something() might just do decorating), do we really need to involve exception handling in such simple cases? How about allowing both paradigms exist in C++?

(Another example is, for small embedded C++ compilers if they don't support exceptions, they can still support "construction fail" handling in this way.)

Well, maybe my comparison is misleading, I am not against structural exception handling, on the contrary, I LOVE exceptions especially for big systems. But when it comes to small embedded systems where both code and data space are scarce, I think twice.

The exception handling frames are things similar to setjmp() and longjmp() which are quite expensive in both execution time and memory use; while the (objp==nullptr) comparison takes only a comparison and a jump. Not to mention some of the compilers don't even support exception handling. In those cases, construction fail can only be dealt with other methods. That reminds me in the old days Turbo Pascal 5.5 OOP can call "Fail" on construction fail, and the newly allocated object will be null.

What about other languages? Does all OOP languages use exception on construction fail cases?

Actually, at the time I learnt C++ there is no exception handling available at all (Turbo C++ 3.0/Borland C++ 3.1). Before that I learnt Turbo Pascal 5.5 which supported "Fail" on dynamic construction fail. But when I move to C++ at that time this make me a bit upset since there is no way to test construction fail without defining an Init() function that actually do the inits. Since then I wondered, why can't constructors return values?

Now I think maybe returning a value from constructor will make the language "inconsistent". If we return a value from a constructor and the runtime system test it, this kind of behavior is a lot different from a normal function call since our code can test it. Maybe this kind of inconsistency is not a good idea when designing a programming language? What do you think?


In the early days of C++ there was no exception handling, yet Bjarne Stroustrup still didn't let constructors to return error conditions. Same did the other OO languages at that time (correct me if I am wrong). Therefore, using exception handling was not their original intention to take care of constructor fails. Then why? I think I found the answer, please refer to my own answer here. Thanks.

Best Answer

Your question indicates a fundamental misunderstanding of the value of the exception mechanism. If the language in question didn't have exceptions, then of course, error codes would be the only way to go. But using error codes in a language that supports exceptions is not often the right answer.

Why?

As it turns out, very often, code really close to the source of a show stopping problem doesn't know what to do when that happens.

Since the code close to the error often doesn't know what to do, there is nothing for that code to do to handle the error except let someone else do that.

With error code returns, every caller must check for errors, even though there is usually nothing they can do but to further propagate the error to their callers (lather, rinse, repeat...)

Enter Exception Handling

Exception handling is a mechanism that allows a separation of the callees that have problems from truly capable error handlers, which are typically rather removed from the source of an error.

Good handlers know how to abort or retry the broader computation being performed, not simply log the error and propagate the error up the call chain. A sign of a good handler is that it doesn't need to propagate errors up the call chain because it handled them.

With exception handling, we typically don't surround individual method calls with exception handling, and that includes constructors and new operations.

Exception handling allows better definition of an exception handler, and at a considerable distance away from the source of the exception, and this is an advantage because such distance usually means a better understanding of what to do in case of errors.

(Exception handling also allows structuring errors, but we'll leave that for another discussion.)


If we haven't convinced you yet compare these code sequences:

objp = new object (); // constructor returns 'false', 'new' returns 'nullptr'.
if (objp != nullptr) {
    do_something(objp);
} else {
    error_handling();
}

with:

objp = new object (); // object throw exception when construction failed

The latter, using exceptions, is much cleaner and more appropriate to an arguable majority of use cases.