The
seemingly elaborate mechanism for initialization, the constructor, should give
you a strong hint about the critical importance placed on initialization in the
language. As Stroustrup was designing C++, one of the first observations he
made about productivity in C was that improper initialization of variables
causes a significant portion of programming problems. These kinds of bugs are
hard to find, and similar issues apply to improper cleanup. Because
constructors allow you to
guarantee
proper initialization and cleanup (the compiler will not allow an object to be
created without the proper constructor calls), you get complete control and
safety.
In
C++, destruction is quite important because objects created with
new
must be explicitly destroyed. In Java, the garbage collector automatically
releases the memory for all objects, so the equivalent cleanup method in Java
isn’t necessary much of the time. In cases where you don’t need
destructor-like behavior, Java’s garbage collector greatly simplifies
programming, and adds much-needed safety in managing memory. Some garbage
collectors are even cleaning up other resources like graphics and file handles.
However, the garbage collector does add a run-time cost, the expense of which
is difficult to put into perspective because of the overall slowness of Java
interpreters at this writing. As this changes, we’ll be able to discover
if the overhead of the garbage collector will preclude the use of Java for
certain types of programs. (One of the issues is the unpredictability of the
garbage collector.)
Because
of the guarantee that all objects will be constructed, there’s actually
more to the constructor than what is shown here. In particular, when you create
new classes using either
composition
or
inheritance
the guarantee of construction also holds, and some additional syntax is
necessary to support this. You’ll learn about composition, inheritance
and how they affect constructors in future chapters.