Re: Throwing Constructor Exceptions and cleaning up
Richard Maher wrote:
Hi,
If when an object's constructor throws an exception that object has not in
fact been intantiated, then what happens to the bits/objects/variables that
were initialized/instantiated before the exception was thrown?
The memory area that the failing constructor was trying to
initialize is garbage. Or "probably garbage," because the
constructor may have done something dumb before throwing up,
like
class BadIdea {
private static BadIdea mostRecentlyCreated;
BadIdea() {
mostRecentlyCreated = this;
throw new Exception("Color me stupid");
}
}
If something like this happens, the incompletely-initialized
object is not garbage because there's an active reference to it.
But if no reference to the incomplete object survives, its
memory is garbage and eligible for collection.
For example, if I open a file, or connect a socket while constructing an
object and then throw an exception before the constructor/instantiation
completes, then what happens to the file or socket connections that were
successfully instantiated?
That's a little different: You're now talking not about the
incompletely initialized new object but about resources that may
have been claimed (and perhaps "orphaned") during initialization.
The short answer is "Don't Do That," and the try/finally block
is often a good prophylactic measure.
a) Garbage Collected in the fullness of time as they're no longer
referenced?
*If* they're no longer referenced. Whether garbage collection
is sufficient to clean up any associated non-memory resources
(sockets, file handles, screen widgets, database sessions, ...)
depends on how the socket/file/screen/database classes have
been written.
b) Destroyed, and o/ride finalize() method that's called immediately?
Stay after class and write on the blackboard one hundred
times: "Finalizers are not destructors."
If the socket/whatever class has a "destructor," it's up to
you to call it, explicitly (often in a finally clause). There is
no automatic destruction of objects in Java.
Recommended reading: "Effective Java" by Joshua Bloch. The
first several sections examine (and advise on) how to deal with
the creation and destruction of Java objects, and when to use
(and when *not* to use!) finalizers.
c) It's considered extremely bad form to do this in a constructor. Have an
init() method instead?
Well, maybe. Depends on the overall design, on how you
intend the class to be used. It *is* bad form to leak resources,
in a constructor or anyplace else. It's also bad form to store a
reference to an incompletely-initialized object -- one common error
is to store the reference as the very last thing the constructor
does, but that's not necessarily safe. (Why not? Hint: If class
Sub extends class Super, what is likely to happen right after
Super's constructor is finished?)
d) Make sure you close the file/Socket before throwing the execption
Or in finally.
e) Something else. . .
Like, "Don't encounter errors" ...?
--
Eric Sosman
esosman@ieee-dot-org.invalid