next up previous contents index
Next: Note Added. Up: Applying the simplify algorithm Previous: return and throw statements   Contents   Index


Explicit constructor invocation statements

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

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$super($...
...\ldots$\verb$, $$e_{n-1}$\verb$) ;$
\end{tabbing}\end{minipage}\end{displaymath}

or

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$this($$...
...\ldots$\verb$, $$e_{n-1}$\verb$) ;$
\end{tabbing}\end{minipage}\end{displaymath}

or

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
$e_0$\verb$.s...
...\ldots$\verb$, $$e_{n-1}$\verb$) ;$
\end{tabbing}\end{minipage}\end{displaymath}

The last form may be used if the superclass is an inner class.

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 $e_0,
\ldots, e_{n-1}$ 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 $C$ is a class which has a constructor of the form

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
$\mbox{\it m}...
...\verb$) ;$ \\
\>$S$ \\
\verb$}$
\end{tabbing}\end{minipage}\end{displaymath}

where $\mbox{\it m}$ is an optional access modifier, each $m_i$ is an optional final modifier, each term $U_i$ is a type, each term $V_i$ is a simple identifier, $v_i$, followed by zero or more bracket pairs, [], $\mbox{\it ts}$ is a list of exceptions in the optional throws clause, each $e_i$ is an expression (which we will assume has type $T_i$), and $S$ 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 $[e_0, \ldots, e_{n-1}]$, yielding $\mbox{\it INITS}$ and $[e_0', \ldots,
e_{n-1}']$. If $\mbox{\it INITS}$ 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:

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$class $...
...b$ $$f_{m-1}$\verb$ ;$ \\
\verb$}$
\end{tabbing}\end{minipage}\end{displaymath}

where the $S_i$ are the types of the $m$ fields $f_i$. In our case $m$ will be $n + r$, the fields $f_0$ to $f_{n-1}$ will be used to store the values of the expressions $e_0$ to $e_{n-1}$ (so $S_0$ to $S_{n-1}$ should be $T_0$ to $T_{n-1}$), and the fields $f_n$ to $f_{m-1}$ will be used to store the values of the parameters $v_0$ to $v_{r-1}$ of the original constructor after the $e_i$ have been evaluated (so the types $T_n$ to $T_{m-1}$ will be the types of those parameters)A.5.

The new private constructor of $C$ now has the form:

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$private...
...b$ ;$ \\
\\
\>$S'$ \\
\verb$}$
\end{tabbing}\end{minipage}\end{displaymath}

where $S'$ is the pre-translated version of $S$. If the original explicit constructor invocation had the alternate form

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$this($$...
...\ldots$\verb$, $$e_{n-1}$\verb$) ;$
\end{tabbing}\end{minipage}\end{displaymath}

the explicit constructor invocation in the new private constructor would be

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
\verb$this($$...
...$$a$\verb$.$$f_{n-1}$\verb$) ;$ \\
\end{tabbing}\end{minipage}\end{displaymath}

If it had the form

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
$e_0$\verb$.s...
...\ldots$\verb$, $$e_{n-1}$\verb$) ;$
\end{tabbing}\end{minipage}\end{displaymath}

the form in the new private constructor would be

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
$a$\verb$.$$f...
...$$a$\verb$.$$f_{n-1}$\verb$) ;$ \\
\end{tabbing}\end{minipage}\end{displaymath}

The new stub constructor has the form

\begin{displaymath}
\begin{minipage}[t]{\linewidth}\begin{tabbing}
$\mbox{\it m}...
... $$v_{r-1}$\verb$)) ;$ \\
\verb$}$
\end{tabbing}\end{minipage}\end{displaymath}

As promised, the this explicit constructor invocation includes an anonymous class creation expression that declares a method eval() in which the precomputation occurs. This method is immediately invoked to return a tuple object containing the results of the precomputation (and the values of the formal parameters of the constructor).

Noteworthy features of this transformation are:



Subsections
next up previous contents index
Next: Note Added. Up: Applying the simplify algorithm Previous: return and throw statements   Contents   Index
Bryan Carpenter 2003-04-15