Java Learning – Constructor chaining
Constructor chaining refers to invoking one constructor from another within the same class. This technique offers several benefits, including:
- Reduction of code redundancy
- Enhancement of code readability
Consider the Java class ColoredPoint2D
, which is equipped with three distinct constructors:
- The default constructor serves as a provision for the class initialization by external utilities such as deserialization mechanisms, Object-Relational Mapping (ORM) tools, etc.
- A constructor that accepts only
x
andy
parameters, facilitating the creation of a Point instance when the Color attribute is undetermined. - A comprehensive constructor that initializes all three fields, acting as the primary means for class instantiation.
class ColoredPoint2D {
private int color;
private int x;
private int y;
public ColoredPoint2D() {
}
public ColoredPoint2D(int x, int y) {
}
public ColoredPoint2D(int color, int x, int y) {
}
public int getX() { return x; }
public void setX(int x) { this.x = x;}
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getColor() { return color; }
public void setColor(int color) { this.color = color; }
}
What should the constructors include to eliminate code redundancy and accommodate the three use cases?
The primary constructor, which accepts three parameters, is designed to receive the complete set of parameters as expected by the invoking code.
public ColoredPoint2D(int color, int x, int y) {
this.color = color;
this.x = x;
this.y = y;
}
The constructor that only accepts x,y
parameters is responsible for determining the color. Given that a constructor already exists for initializing the coordinates, we aim to prevent code duplication.
To achieve this, we employ constructor chaining
to invoke another constructor that is already equipped to initialize the x,y
parameters. This is accomplished using this()
, which is the syntax for invoking a constructor. Without it, we would be calling a standard method instead.
public ColoredPoint2D(int x, int y) {
this(0xFFFF0000, x, y);
}
And we use the same line of thought for the default constructor
public ColoredPoint2D() {
this(0xFFFF0000, 0, 0);
}
Code structured this way adheres to optimal development practices by eliminating code redundancy and centralizing business logic.
This approach not only simplifies future modifications but also mitigates the risk of unforeseen bugs that may arise from overlooking duplicate initializations in various locations.
The final class definition:
class ColoredPoint2D {
private int color;
private int x;
private int y;
public ColoredPoint2D() {
this(0xFFFF0000, 0, 0);
}
public ColoredPoint2D(int x, int y) {
this(0xFFFF0000, x, y);
}
public ColoredPoint2D(int color, int x, int y) {
this.color = color;
this.x = x;
this.y = y;
}
public int getX() { return x; }
public void setX(int x) { this.x = x;}
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getColor() { return color; }
public void setColor(int color) { this.color = color; }
}
Rules to know:
- The
this()
should be the first statement in the constructor body. - You can add any other code after the
this()
statement.