Explicit constructor invocations appear as the first statement
in the body of some other constructor. Typically they invoke
a constructor of a superclass, although they may also invoke an
alternative constructor of the current class. The syntax is either
Devising transformations of the source program that allow for simplification of expressions in explicit constructor invocations is complicated by two restrictions. The first is that no statement in the body of the constructor can appear before the invocation. Ultimately any scheme that allows for simplification of composite expressions will require the declaration of auxilliary variables before the explicit constructor invocation is processed. At first sight this looks impossible.
There is at least one solution, however. Java allows a constructor to ``dispatch'' some initializations to another constructor in the same class by using the this form of explicit constructor invocation. If we divide the function of the original constructor across two constructors, a formal parameter of the second constructor can can fulfil the role of the required auxilliary variable. The first constructor does the precomputations; the formal parameter of the second constructor is the name through which precomputed results are accessed--the name of the temporary, so to speak.
For this to work our ``first'' constructor must somehow embed the precomputations in a this explicit constructor invocation. It is fairly clear that putting general initialization code in the explicit constructor invocation of the first constructor will require invocation some sort of auxilliary method. At this point the second restriction alluded to above becomes important: in Java the subexpressions that appear in explicit constructor invocations are considered to be evaluated in a static context. This means that they cannot, for example, access instance variables or instance methods of the object being created. (They can however use static variables and methods of the current class, its superclasses, and its lexically enclosing classes.)
The static context means that any auxilliary method invoked cannot be an instance method of the current class. However the method must have access to the static context of this class. It could be a static method (or, say, a constructor of a nested static class). But we have to consider the possibility that the current class is an inner class; such static members cannot be defined in inner classes.
Luckily Java allows us to embed a definition of a method within the explicit constructor invocation itself, but using an anonymous class creation expression. This gives us access to the static context of the original class, while avoiding the problems of invoking instance methods of the original class.
In the following discussion our ``first constructor'' will be called the stub constructor. The ``second constructor'' will be called the private constructor.
To begin, suppose is a class which has a constructor of the form
, is a list of exceptions in the optional throws clause, each is an expression (which we will assume has type ), and is a sequence of statements. The other two forms of explicit constructor invocation can be handled by straightforward modifications to our basic scheme, which will be indicated as we go.
In a trivial way we can generalize the simplify algorithm to apply to an ordered list of expressions (treat the ordered list like a non-composite expression with no direct accesses, and the elements of the list like singly-referenced subexpressions). Apply this algorithm to the ordered list of expressions , yielding and . If is non-empty we transform the program as follows.
To support the transformation we will need to introduce an auxilliary
``tuple class'' used to store multiple results of the precomputation.
This class can have the general form:
The new private constructor of now has the form:
The new stub constructor has the form
Noteworthy features of this transformation are: