A copy constructor creates an object from another object of the same class. It should explicitly initialize every eligible field that represents the new object’s state.
A class can evolve after its copy constructor is written. When a new field is added but the copy constructor is not updated, the copied object
silently keeps Java’s default value for that field, such as null, zero, or false. The result is an incomplete copy that can
behave differently from its source and cause failures far from the constructor.
This rule raises one issue on a constructor whose sole parameter has the same type as the enclosing class when one or more eligible fields are not
explicitly initialized. The declarations of the omitted fields are identified as secondary locations. Eligible fields are instance fields declared in
the enclosing class that are not transient and do not have declaration initializers.
Initialize each eligible field explicitly. Any explicit write to an eligible field counts as initialization. This includes assignments of any
value, such as null, zero, or false, as well as increment and decrement operations. Use an explicit assignment when a field
should intentionally be reset instead of copied.
class Account {
private static int accountCount;
private String owner;
private String note;
private int retryCount;
private boolean enabled;
private transient Object cachedSession;
private Object auditData = new Object();
Account(Account other) { // Noncompliant: "note", "retryCount", and "enabled" are not explicitly initialized
this.owner = other.owner;
}
}
class Account {
private static int accountCount;
private String owner;
private String note;
private int retryCount;
private boolean enabled;
private transient Object cachedSession;
private Object auditData = new Object();
Account(Account other) {
this.owner = other.owner;
this.note = null; // intentional reset
this.retryCount = 0; // intentional reset
this.enabled = false; // intentional reset
}
}
Static fields do not belong to an individual object and are not considered. Fields with declaration initializers are already initialized
explicitly, and transient fields often represent state that should not be copied, so the rule does not require assignments for them.
The rule does not attempt to determine whether copying a field should be shallow or deep, or whether the value assigned to a field is correct. It only checks whether each eligible field is explicitly initialized.
Explicit writes made in instance initializer blocks, directly in the constructor, through constructor delegation, or through instance helper
methods called on this count when the rule can resolve the invoked code. It does not raise an issue when required semantic information or
an invoked initialization path cannot be resolved.