Just because the reference to the list is immutable doesn't mean that the list it refers to is immutable.
Even if list
was made final
this would be allowed
// changing the object which list refers to
example.getList().add("stuff");
but this would not allowed:
// changing list
example.list = new ArrayList<String>(); // assuming list is public
In order to make the list immutable (prevent also the first line), I suggest you use Collections.unmodifiableList
:
public class Example {
final private ArrayList<String> list;
Example(ArrayList<String> listArg) {
list = Collections.unmodifiableList(listArg);
}
}
(Note that this creates an unmodifiable view of the list. If someone is holding on to the original reference, then the list can still be modified through that.)
With a String this behaviour isnt possible. So what is the difference here?
That is because a String
is already immutable (unmodifiable) just as the list would be if you turned it into an unmodifiableList.
Comparison:
String data structure | List data structure
.-------------------------+------------------------------------.
Immutable | String | Collection.unmodifiableList(...) |
-----------+-------------------------+------------------------------------|
Mutable | StringBuffer | ArrayList |
'-------------------------+------------------------------------'