It depends on what the goal is. Can the list never change after construction? Can it change but only the ColumnWrapper
can do so? Or can it change and everyone is allowed to do that?
If the list can not change after construction, consider using an ImmutableList (from google's guava). You should then declare the field columnNames
and the return value of getNames()
to be of that type. You then either create an immutable list during construction or use that type for the constructor argument as well.
If the list can change after construction (but only ColumnsWrapper
can do so), the getter should return an unmodifiableList. Note that this will cause exceptions if the client of your class tries to manipulate the list. You should then also copy during construction (as you currently do).
In any way should you document the behavior with comments on the respective public members (i.e. the constructor and the getter).
Edit
Ok, so the class has to be immutable. As @rolfl explains, it can be subclassed so this is not yet the case. You can either make the class final or make the constructor private and provide a static factory method.
Furthermore you have to make sure, that the list can not be modified. The easiest and most intention revealing way I know of is the ImmutableList I mentioned above. Another solution would look like this:
public class ColumnsWrapper implements Columns {
private final List<String> columnNamesUnmodifiable;
public ColumnsWrapper(List<String> columnNames) {
List<String> columnNamesCopy = new ArrayList<>(columnNames);
columnNamesUnmodifiable = Collections.unmodifiableList(columnNamesCopy);
}
// OPTION A
@Override
public List<String> getNamesUnmodifiable() {
return columnNamesUnmodifiable;
}
// OPTION B
@Override
public Iterable<String> getNamesUnmodifiable() {
return columnNamesUnmodifiable;
}
}
Note that I changed the name to inform callers that they will get an unmodifiable instance.
I also provided another additional option (you have to choose one) with a different return type. If you are sure that callers will only iterate over the returned instance (as is often the case) the iterable will suffice. But it can not be used to add methods and since removal is an optional method (i.e. many iterators support no removal) it better conveys immutability.
I any way the interface documentation should also make that clear.
return Collections.unmodifiableList(columnNames);
instead ofreturn new ArrayList<String>(columnNames);
would be more efficient. \$\endgroup\$getNames
method, not in the constructor. It is an optimisation but I would not call it premature in the sense that it does not make the code more complex and will clearly perform better (if only because it will generate less garbage) so why not do it? \$\endgroup\$return
. :) I still advice to already make the instance owned by the class unmodifiable. This makes the class truly immutable and allows the getter to do no extra work. \$\endgroup\$