Mutable objects are those whose state can be changed. For instance, an array is mutable, but a String is not. Private mutable class members should
never be returned to a caller or accepted and stored directly. Doing so leaves you vulnerable to unexpected changes in your class state.
Instead use an unmodifiable Collection
(via Collections.unmodifiableCollection
,
Collections.unmodifiableList
, …​) or make a copy of the mutable object, and store or return the copy instead.
This rule checks that private arrays, collections and Dates are not stored or returned directly.
Exceptions
The rule violation is not reported for mutable values stored in private methods if no non-private methods directly passes a mutable parameter to
them.
Similarly, rule violations are not reported for mutable values returned by a private getter if that getter’s value is not directly exposed by a
non-private method.
Noncompliant code example
class A {
private String[] strings;
public A () {
strings = new String[]{"first", "second"};
}
public String[] getStrings() {
return strings; // Noncompliant
}
public void setStrings(String[] strings) {
this.strings = strings; // Noncompliant
}
}
public class B {
private A a = new A(); // At this point a.strings = {"first", "second"};
public void wreakHavoc() {
a.getStrings()[0] = "yellow"; // a.strings = {"yellow", "second"};
}
}
Compliant solution
class A {
private String [] strings;
public A () {
strings = new String[]{"first", "second"};
}
public String[] getStrings() {
return getStringsInternal().clone();
}
private String[] getStringsInternal() {
return strings;
}
private void setStringsInternal(String[] strings) {
this.strings = strings;
}
public void setStrings(String[] strings) {
this.strings = strings.clone();
}
}
public class B {
private A a = new A(); // At this point a.strings = {"first", "second"};
public void wreakHavoc() {
a.getStrings()[0] = "yellow"; // a.strings = {"first", "second"};
}
}