This is a sentence from Java Concurrency in Practice
Shared read-only objects include immutable and effectively immutable objects.
Here's my understanding from a bit of googling and finding this article. An Effectively Immutable Object is an object that contains fields that can be mutated, but it doesn't let anything mutate those fields because it never gives you a reference to them. For example, lets say you create a class with an ArrayList
in it. ArrayList
s are mutable, but if your class always returns a copy of the ArrayList and everything else in your class is immutable, then your class has become effectively immutable: There's no way to mutate the state of an instance of your class.
The blog post gives this as an example of an effectively immutable class:
import java.awt.*;
public class Line {
private final Point start;
private final Point end;
public Line(final Point start, final Point end) {
this.start = new Point(start);
this.end = new Point(end);
}
public void draw() {
//...
}
public Point getStart() {
return new Point(start);
}
public Point getEnd() {
return new Point(end);
}
}
Point
objects are mutable, but that's ok, because this class does not give anyone the direct reference to it's Point instances. Instead, it returns a new instance with the same value in it. That way, nobody can mutate the state of the Line
class. This makes the Line
class effectively immutable.
So how is this different from a truly immutable class? A truly immutable class has fields that are also immutable. Lets imagine Line
was truly immutable. To do that we're also going to have to imagine that Point
is immutable. Making these assumptions, the getStart()
method could have been able to be written like this:
public Point getStart() {
return start;
}