Java Reference
In-Depth Information
main should catch it, so it seems a safe bet that the program will print I told you so . But if you
tried running it, you found that it does nothing of the sort: It throws a StackOverflowError . Why?
Like most programs that throw a StackOverflowError , this one contains an infinite recursion.
When you invoke a constructor, the instance variable initializers run before the body of the
constructor [JLS 12.5]. In this case, the initializer for the variable internalInstance invokes the
constructor recursively. That constructor, in turn, initializes its own internalInstance field by
invoking the Reluctant constructor again and so on, ad infinitum. These recursive invocations
cause a StackOverflowError before the constructor body ever gets a chance to execute. Because
StackOverflowError is a subtype of Error rather than Exception , the catch clause in main doesn't
catch it.
It is not uncommon for an object to contain instances of its own type. This happens, for example, in
linked list nodes, tree nodes, and graph nodes. You must initialize such contained instances
carefully to avoid a StackOverflowError .
As for the nominal topic of this puzzle— constructors declared to throw exceptions— note that a
constructor must declare any checked exceptions thrown by its instance initializers. This
program, which illustrates a common service-provider pattern, won't compile, because it violates
this rule:
public class Car {
private static Class engineClass = ... ; // Service provider
private Engine engine = (Engine) engineClass.newInstance();
public Car() { } // Throws two checked exceptions!
}
Although it has no body, the constructor throws two checked exceptions: InstantiationException
and IllegalAccessException . They are thrown by Class.newInstance , which is called when
initializing the engine field. The best way to fix this is to create a private static helper method that
computes the initial value of the field and handles exceptions appropriately. In this case, let's
assume that the Class object referred to by engineClass was chosen to guarantee that it is both
accessible and instantiable. The following version of Car compiles without error:
// Fixed - instance initializers don't throw checked exceptions
public class Car {
private static Class engineClass = ... ;
private Engine engine = newEngine();
 
 
Search WWH ::




Custom Search