Is there any way to implement preliminary calculations before an invocation of super(...)
or this(...)
constructor? Consider the following example:
public class Test {
private final int n;
private final int m;
private final int[] store;
public Test(int n, int m) {
/* This is common (most generic) constructor of the class Test.
It is desirable to invoke it via this(...) call
from any other constructor of this class
since it contains some common initialization tasks,
which are better to concentrate in one place instead
of scattering them throught the class, due to
maintainability and security reasons. */
this.n = n;
this.m = m;
store = new int[n];
// ...
}
public Test(Object data) {
/* This is specific constructor. It depends on some parameters
which must be processed prior to a call of the Test(int n, int m)
constructor to get its arguments. The problem is, this processing
cannot appear here because a call to this(...) must be the first
statement in a constructor. */
int a; // Must be calculated via lengthy code
int b; // Must be calculated via lengthy code
this(a, b); // <- Compiler error here
// ... further initialization
}
}
How can I implement the parameters calculation? The simplest solution is to replace the specific constructor by a static method. But what if it must be a constructor and nothing else (e.g. there is a chance that it may be used in a descendant class). The best solution I've found so far is to introduce a static inner class containing all parameters of the common constructor and use it to store the parameters at the beginning of the specific constructor:
public class Test {
private final int n;
private final int m;
private final int[] store;
protected static class ConstrParams {
int nParam;
int mParam;
ConstrParams(int n, int m) {
nParam = n;
mParam = m;
}
}
protected Test(ConstrParams params) {
/* This is the common constructor now.
It is marked as protected because it is essentially auxiliary,
as well as the class ConstrParams is. */
n = params.nParam;
m = params.mParam;
store = new int[n];
// ...
}
public Test(int n, int m) {
// This is public interface to the common constructor.
this(new ConstrParams(n, m));
}
private static ConstrParams makeParams(Object data) {
/* This is a procedure that inserts lengthy calculations
before constructor chain invocation. */
int a = 0; // Calculate a from data
int b = 0; // Calculate b from data
return new ConstrParams(a, b);
}
public Test(Object data) {
// Specific constructor. Now compiles successfully.
this(makeParams(data));
// ... further initialization
}
}
Is there any better workaround? The case when Test(Object data)
must call some super(...)
constructor instead of this(...)
is even worse since we get less flexibility in this case and often cannot change the ancestor class's code.