Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.
public final class ImmutableClass {

    private StringBuffer name;

    public ImmutableClass(StringBuffer name) {
        this.name=name;
    }
    public StringBuffer getName() {
        return name;
    }
}

Points that I have considered:

  1. Make the class final so that it cannot be extended
  2. Do not provide public mutator methods
  3. Keep the instance variables private

Are the above mentioned considerations sufficient?

share|improve this question

migrated from codereview.stackexchange.com Dec 6 '13 at 4:30

This question came from our site for peer programmer code reviews.

8  
The StringBuffer can be modified after you pass it as an argument to your class, it can also be modified after you return it with getName() so no, it's not immutable. BTW StringBuffer shouldn't be used and StringBuilder replaced it nearly ten years ago. –  Peter Lawrey Dec 6 '13 at 8:24
1  
Check this also: @Immutable –  yegor256 Dec 6 '13 at 16:47

2 Answers 2

up vote 10 down vote accepted

Consider:

ImmutableClass a = new ImmutableClass(new StringBuffer("hello"));
a.getName().append(" world");
System.out.println(a.getName()); // prints "hello world"

The above allows the caller to mutate the value of name. Or:

StringBuffer b = new StringBuffer("hello");
ImmutableClass a = new ImmutableClass(b);
System.out.println(a.getName()); // prints "hello"
b.append(" world");
System.out.println(a.getName()); // prints "hello world"

The above is similar, and shows that a change to something else can affect the apparent value of a.

With the ability to do the above, your class cannot be considered "immutable" by any definition. However, if you were to replace StringBuffer with String, then your class would be immutable (because in Java, String is immutable).

share|improve this answer
    
I got your point. Does it mean that members of the class have to be immutable themselves(if they can be accessed in some way like in my example) to achieve overall immutability for the class? –  n1234 Dec 6 '13 at 4:59
1  
@n1234: Basically, yes. Immutability must include all the parts a user can see and touch by any means. If you wanted to clone the StringBuilder, you could do that and still consider the type immutable...but the one you're holding must never be accessible to the outside world (because it's mutable, and you can't keep it from being so). –  cHao Dec 6 '13 at 5:45
2  
even with String inside, one would need final modifier in field declaration private final String name; to guarantee immutability in multithreaded context, see eg About reference to object before object's constructor is finished. Consider editing your (otherwise very good) answer to account for that –  gnat Dec 6 '13 at 6:10
    
Came to comment about same thing - even the field should have the final modifier. All the fields should have. This will ensure that you won't modify it accidentally. If you do, the compiler will complain. This also means, every time a field changes, you should create a totally new object, thus immutable. –  Sundeep Dec 6 '13 at 6:36
1  
@Sundeep I mean that if you never set the value outside the constructor or if you use lazy instantiation (where you can't use final) then it can be considered immutable as long as the user never sees it change. As for thread safety: check gnat's link: final enforces some volatile-like semantics (reads always seeing the value it was set to) –  ratchet freak Dec 6 '13 at 11:03

Whether the class is immutable or not depends upon whether you are intending it to encapsulate the identity of the StringBuffer or the contents thereof. The design of the class suggests that it encapsulates the identity of the StringBuffer; because it will never identify any StringBuffer other than the instance identified to it at instantiation, the class ImmutableClass may be regarded as immutable. Nonetheless, instances of ImmutableClass which encapsulate a particular StringBuffer should not be exposed to any code which cannot be trusted with an unguarded reference to that StringBuffer.

The pattern of having an immutable class identify a mutable object is not very common, but there are a few cases where it may be appropriate. Perhaps the most natural example would be a class whose purpose is to set a mutable object to some particular state; such a class would encapsulate a reference to the object in question along with the desired state. If the identity of the object and the state to which it should be set are both immutable, than the class encapsulating those things would likewise be immutable. A key aspect of such designs is that the class which encapsulates the identity of the mutable object doesn't care regard the state of that object as being parts of its own state. That situation is very different from a type which holds a reference to an unshared mutable object for the purpose of encapsulating its own state therein. An object which encapsulates mutable state anywhere, whether in itself or in another object, is mutable. Merely holding a reference to a mutable object, however, does not imply encapsulating state thereof.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.