3

I'd like to create a few immutable objects for my codebase. What's the best way to really deliver the message that a given class is intended to be immutable? Should I make all of my fields final, and initialize during object construction? (This seems really awkward...) Should I create some Immutable interface, and have objects implement it? (Since Java doesn't have some standard interface behind this, I thought they had some other way of dealing with it.) What's the standard way this is dealt with? (If it's simply done by adding a bunch of comments around the fields exclaiming that they shouldn't be modified once initialized, that's fine too.)

2
  • 1
    What exactly are you concerned about? Is it that your coworkers won't understand and will modify your class to make it mutable? Commented May 20, 2013 at 23:20
  • yeah, exactly. I'm afraid that people who see the code in the future won't fully appreciate the fact that the design behind the class was that it's immutable, and they may create setters for the future and such. Commented May 20, 2013 at 23:30

3 Answers 3

8

Should I make all of my fields final, and initialize during object construction?

Yes. And ensure that those types are themselves immutable, or that you create copies when you return values from getter methods. And make the class itself final. (Otherwise your class on its own may be immutable, but that doesn't mean that any instance of your class would be immutable - because it could be an instance of a mutable subclass.)

(This seems really awkward...)

It's hard to know what to suggest without knowing how you find it to be awkward - but the builder pattern can often be useful. I usually use a nested static class for that, often with a static factory method. So you end up with:

Foo foo = Foo.newBuilder() .setName("asd") .setPoints(10) .setOtherThings("whatever") .build(); 
Sign up to request clarification or add additional context in comments.

6 Comments

+1 for And ensure that those types are themselves immutable. What you say about an Immutable interface or annotation as metadata similar to the Serializable interface?
@Craig you're thinking of this.
Thanks Jon, this answered my question. To answer your question, I simply found making every field final awkward because I don't usually see that in code I've seen so far.
You don't have to make them final if you don't have setters, but doing so clearly signals to readers of your code what the intent is, which is at the core of good programming. Also, fields don't have to be immutable - if they aren't, have getters return a copy.
You got my +1 already :) I agree with erring to use final, because the code signal to noise ratio of using final for fields is high. And everyone, including the author, is kept "on reservation". I was just qualifying the answer.
|
5

Yes and no. Making all fields final is not a guarantee in and of itself. If you'd like to get really in-depth with this there are a number of chapters in Effective Java by Joshua Bloch dealing with immutability and the considerations involved. Item 15 in Effective Java covers the bulk of it and references the other items in question.

He offers these five steps:

  1. Don’t provide any methods that modify the object’s state (known as muta- tors).

  2. Ensure that the class can’t be extended.

  3. Make all fields final.

  4. Make all fields private.

  5. Ensure exclusive access to any mutable components.

One way to learn how to do all of this is to see how the language designers make classes immutable by reviewing the source for classes like String which are immutable (for example see http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java).

2 Comments

Here is what Joshua Bloch wrote in Effective Java about the 5th bullet: If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference or return the object reference from an accessor
This is also known as making defensive copies.
1

Write a unit test that will fail if your coworkers make the class mutable.

Using Mutability Detector, you can write a test like this:

import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable; @Test public void isImmutable() { assertImmutable(MyImmutableThing.class) } 

If a coworker comes along, and, for example, adds a setter method to your class, the test will fail. Your use case is one of the core purposes of Mutability Detector.

Disclaimer: I wrote it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.