21

This is a sentence from Java Concurrency in Practice

Shared read-only objects include immutable and effectively immutable objects.

What are the differences between immutable and effectively immutable objects?

sheidaei
  • 9,842
  • 20
  • 63
  • 86
  • See [Do effectively immutable objects make sense](http://stackoverflow.com/questions/8707426/do-effectively-immutable-objects-make-sense) which also mentions the book to which you refer. – Bobulous May 21 '13 at 20:04
  • See also [Must all properties of an immutable object be final?](http://stackoverflow.com/questions/16061030/must-all-properties-of-an-immutable-object-be-final) – assylias May 21 '13 at 20:20
  • I've implemented a full Java immutability detector and provided it as an answer to another nearby question. It fully encapsulates "effective immutability". https://stackoverflow.com/questions/37087809/how-to-find-out-if-a-class-is-immutable/75043881#75043881 – chaotic3quilibrium Jan 07 '23 at 22:32

4 Answers4

17

Instances of a class that is not extensible and whose fields are all final and themselves immutable are immutable.

Instances of a class whose fields cannot be mutated because of details of its methods are effectively immutable. For example:

final class C {
  final boolean canChange;
  private int x;
  C(boolean canChange) { this.canChange = canChange; }
  public void setX(int newX) {
    if (canChange) {
      this.x = newX;
    } else {
      throw new IllegalStateException();
    }
  }
}

Some instances of C are effectively immutable and some are not.

Another example is zero-length arrays. They are effectively immutable even though their containing class is not provably immutable since there is no element of them which can be changed.


Joe-E uses a verifier to prove that some classes only allow for immutable instances. Anything marked with the Immutable marker interface are checked and certain classes like String (effectively immutable since its char[] does not escape) are grandfathered in as immutable.

Joe-E: A Security-Oriented Subset of Java says

The Immutable interface, defined by the Joe-E library, is treated specially by the language: the Joe-E verifier checks that every object implementing this interface will be (deeply) immutable, and raises a compile-time error if this cannot be automatically verified.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • 1
    "Instances of a class whose fields cannot be mutated because of details of its methods are effectively immutable" - this is inprecise. _Effectively Immutable_ can be any object as long as it is not mutated after it is _safley publushed_ (e.g. via volatile reference or such) – Op De Cirkel Nov 24 '15 at 06:15
  • @OpDeCirkel, The -able suffix on "immutable" makes the meaning "not capable of change" not just "not mutated." If you have information indicating that the plain meaning is not what Goetz et al meant then please add an answer and I'll upvote. – Mike Samuel Nov 24 '15 at 18:13
  • 1
    JCP 3.5.4: Objects that are not technically immutable, but whose state *will not be modified* after publication, are called effectively immutable. - This definition includes broader set then objects that do not have methods that mutate their state. Just having convetion that the object should not be mutated after safe publishing is enough to be effectively immutable. – Op De Cirkel Nov 27 '15 at 20:18
  • 1
    Also the definition (and the question) talks about effectively immutable *object*, not classes. In the same section I mentioned before - JCP 3.5.4 - Using java.util.Date is used as example discussed in context of effective immtability (though it has methods that can mutate its state) – Op De Cirkel Nov 27 '15 at 20:28
  • Another problem applying _effective immutability_ concept to classes is that will become much more complicated in cases when the class has package private method that mutates its state, and public methods that do not. Is this _effectively immtable_ or not? – Op De Cirkel Nov 27 '15 at 20:38
  • @OpDeCirkel, Thanks for the cite. If write that up as an answer, I'll upvote it and recommend that it be accepted as the accepted answer. – Mike Samuel Nov 28 '15 at 05:16
13

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. ArrayLists 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;
}
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • Terminology varies, but I would consider "effective immutability" as a characteristic of object *instances* rather than types. If there is no execution path via which a reference to a some particular instance could ever be exposed to code that might mutate it, that instance would be effectively immutable, even if its class is not. I would consider an object which only holds values and references to either immutable types or effectively-immutable instances, and does not expose any method of changing its own shape, to be immutable. – supercat Jun 13 '13 at 19:36
  • @supercat from the English meaning of the phrase, that makes sense. – Daniel Kaplan Jun 13 '13 at 19:39
3

Take a look at this answer:

effectively immutable and immutable The difference between effectively immutable and immutable is that in the first case you still need to publish the objects in a safe way. For the truly immutable objects that isn't needed. So truly immutable objects are preferred because they are easier to publish, the reasons I stated above say why you might prefer unsynchronized publication.

https://stackoverflow.com/a/7887675/1007546

Community
  • 1
  • 1
jsurls
  • 365
  • 2
  • 11
2

Immutable objects completely encapsulates their internal state and they do not allow modification of that state after construction (possibly with the use of final, etc) therefore they are safe to share between multiple threads because reading from a shared object is not harmful from multiple threads.

Effectively immutable objects may change their state prior to being shared between multiple threads, but after they are "published" (ie multiple references are given to several threads) they protect themselves from modification.

Immutable objects prevent you from using useful software engineering practices like lazy initialization because in order to lazy init a property or field they have to be mutable violating the carefree concurrency sharing property of them. Effectively immutable objects relax these constraints to get a best of both worlds approach by carefully knowing when they can safely modify their internal state and when it is forbidden.

chubbsondubs
  • 37,646
  • 24
  • 106
  • 138
  • 1
    Yes String is immutable and prevents you from modifying its internal state directly, but it does use lazy init when computing its hashcode. So technically String is effectively immutable. – chubbsondubs May 29 '13 at 02:38