I realize there are special classes for which this general question doesn't apply, but for the simple ones, when we have multiple constructors, and the parameters of one are a clean subset of another, is it better to call the constructor with the longer list from the one with the shorter list, or vice versa? Why?
public class A {
int x;
int y;
int z;
public A() {
this(0);
}
public A(int x) {
this (x, 0);
}
public A(int x, int y) {
this(x, y, 0);
}
public A(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
// some setup stuff needed for all A
}
}
Or
public class A {
int x;
int y;
int z;
public A(int x, int y, int z) {
this(x, y);
this.z = z;
}
public A(int x, int y) {
this(x);
this.y = y;
}
public A(int x) {
this();
this.x = x;
}
public A() {
// some setup stuff needed for all A
}
}
Constructor chaining can be achieved in any order.
Constructor chaining is the process of calling a sequence of constructors. We can do it in two ways: by using this() keyword for chaining constructors in the same class. by using super() keyword for chaining constructors from the parent class.
Rules of Constructor Chaining An expression that uses this keyword must be the first line of the constructor. Order does not matter in constructor chaining.
Java Constructor Chaining in the Same Class You can create multiple constructors in the same class, each with a different number of arguments that it accepts. To call one of the constructors in another constructor (of the same class), use the keyword this().
Have a look at the second variant:
public A(int x, int y, int z) {
this(x, y);
this.z = z;
}
public A(int x, int y) {
this(x);
this.y = y;
}
public A(int x) {
this();
this.x = x;
}
public A() {
// some setup stuff needed for all A
}
Note that this “stuff needed for all A” is impossible to set up, if it requires the actual values of x
, y
, z
. The only way to fix that, is to let the default constructor do that work using the default values of x
, y
, z
and then overwrite its results in the calling constructor, using the specified non-default values. That’s a no-go if these setup work has noticeable side effects, but even without side effects it may also have a negative effect on the performance, considering the worst case, that the A(int x, int y, int z)
constructor performs that work four times.
Besides that, there are (at least) three scenarios, where your second variant doesn’t work, even without such setup work:
As already explained by Codebender, the parameter lists are not required to be a subset of each other.
public A(TypeA a) {
this(a, DEFAULT_B);
}
public A(TypeB b) {
this (DEFAULT_A, b);
}
public A(TypeA a, TypeB b) {
…
}
the fields might be final
. Then, the last constructor in the chain, which does not invoke another constructor of this class, must initialize all final
fields while the delegating constructors are not allowed to write into these final
fields at all.
public class A {
final int x, y, z;
public A() {
this(0);
}
public A(int x) {
this (x, 0);
}
public A(int x, int y) {
this(x, y, 0);
}
public A(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
// optionally, some setup stuff needed for all A
}
}
Some of the fields are defined in the superclass and required to be initialized via the constructor. Similarly to the final
field initialization, only the last constructor in the chain can invoke the super
constructor while the others can’t invoke a super
constructor, so only a constructor knowing the appropriate values can be that last one.
public class A extends B{
int z;// B has x and y
public A() {
this(0);
}
public A(int x) {
this (x, 0);
}
public A(int x, int y) {
this(x, y, 0);
}
public A(int x, int y, int z) {
super(x, y);
this.z = z;
// optionally, some setup stuff needed for all A
}
}
Since there are a lot of scenarios where the second variant doesn’t work, I would not use it in working scenarios either, as whenever something is merely a stylistic question, you should strive for consistency.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With