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
[],
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: