3

I faced this question in one interview. I explained that String is immutable and StringBuffer is mutable class. I don't know very much about mutable and immutable and also don't know the exact answer. What are the key concepts to be able to distinguish the two ideas? Is there a performance impact when chosing one over the other?

2
  • 5
    It's not immediately obvious but the word is derived from mutate, which is what you do whenever you change the value of something in an object; you are mutating that instance of that object. Immutable things cannot be mutated, that means their values may not be changed. Oct 11, 2013 at 19:55
  • 2
    or for that matter Integer(immutable) vs AtomicInteger (mutable)
    – KNU
    Oct 2, 2014 at 17:42

8 Answers 8

44

An immutable class is immutable, as in, it is not mutable. You cannot change it. If you have x::String, you can be absolutely 100% certain that x will never ever change ever (or at least, if it does, people are abusing the flexibility of your language and you have every right to tell them where to go).

A mutable class is not immutable. You can change it, other people can change it, and you can't rely on it being the same. It could be changed in another thread, you can't even be sure of it being in the same state from line to line unless you have good locking.

The ability to alter the state of the object is the key concept, but the story doesn't end there. You might want to choose an immutable class in a threaded environment, because now you don't need to worry about locking, because nobody can write to it anyway. You might want to choose immutable objects in a large system, because you can't be certain that nobody else has a handle on that input parameter and won't change it out from under you the first chance they get. You might want to choose immutable objects because they make reasoning about the behaviour of your code in small units possible--as in, if everything about a function relies on immutable data, you can look at that function in isolation, guaranteed.

There are performance impacts, but it's not all one way. Immutable objects enable a lot of optimisations you just can't do on mutable data, like aggressively sharing memory (because hey, it can't change) or more aggressive inlining. Mutable data tends to get performance increases when you need to make a lot of changes to blocks of memory.

If you're interested in seeing somewhere where immutability really shines, take a look at a language like Haskell, which was designed from the ground up for immutability, enabling language-level support for things like laziness and a lot of optimisation.

3
  • 15
    "An immutable class is immutable, as in, it is not mutable.": To be precise, one should say that instances of that class can be / cannot be changed. Mutability refers to instances, not the the class itself.
    – Giorgio
    Jan 19, 2015 at 14:28
  • 1
    The first line sent me on a mind blowing trip... Jul 7, 2015 at 0:23
  • There must be some point up to which an instance is mutable, so that you can have a string "Hello" and a string "World". And there is a point where it stops being mutable.
    – gnasher729
    Oct 27, 2022 at 7:54
9

To properly define mutable and immutable classes, one must first define what it means for an object instance to be mutable. An object instance is mutable if there is any possible(*) means via which the state encapsulated thereby might be modified. An object instance is immutable if its state cannot possibly be changed. An class is immutable if all instances of that class are guaranteed to be immutable, regardless of who might hold references to them.

(*) There are certain approaches like Reflection where malicious code could modify just about anything; most discussions of immutability focus on things code may "legitimately" do, and regard such Reflection tricks as illegitimate. Outside of security applications, the normal goal is to have objects work correctly for well-behaved clients; if a class behaves oddly when clients do illegitimate things, that's the clients' problem.

Many discussions of immutability ignore the fact that while all instances of an immutable class are immutable, instances of a mutable class can also be immutable. Some discussions of mutability suggest that for a class to "really" be immutable, all fields thereof must also be immutable types. Not only is that not true, but in many cases it would represent an almost-impossible goal given the absence of immutable array types. What is necessary is that an immutable object must always be certain that no reference to any mutable object in which it holds state will ever be exposed to any code that might mutate it. Anything that outside code might legitimately want to do with the encapsulated object must be done through methods implemented by or on behalf of the immutable containing object.

It would be helpful if .NET or Java had declarative means of specifying that certain objects, despite being of mutable type, should never be modified. Unfortunately, no such feature exists. Despite that, a major key to writing correct and efficient code is knowing which references identify things which are known to be of immutable classes, which ones identify (what must be) immutable instances of possibly-mutable classes, which ones identify unshared mutable instances of mutable classes, and which ones fit none of those patterns (generally because they identify "entities"). Many kinds of bugs, some of which may be very obscure, can result from using one of the above kinds of reference as though it was another.

PS--A framework may achieve the efficiency and robustness of const validation without the hassles of C++-style "const correctness" if

  • Distinct storage types exist for "references to entity", "unrestricted reference to potentially-mutable value", "read-only reference to potentially-mutable value", and "reference to immutable value"

  • Values are cloneable [cloning could be largely automated if the types of contained references are distinguished]

  • Members can be marked based upon whether they should be invokable upon read-only or immutable references

  • Each object instance includes a flag saying whether unrestricted references to it may exist

  • Any reference can be implicitly converted to a read-only reference; an unrestricted reference can also be implicitly converted to an immutable reference by making a new immutable clone. A read-only reference can be implicitly converted to immutable, making a new immutable clone if needed. A new mutable object may be cloned from any reference.

An essential aspect of the "entity" versus "value" distinction would be that an object is a "value" only if either (1) it is immutable, or (2) it has a single owner, and no reference of any sort exists to the object which is not under the control of that owner. Trying to regain control over all references that might exist to an object which has ever been freely exposed to outside code would be impossible, and a strictly-compiler-enforced mechanism would probably be too restrictive to be useful, but even if things worked like C++ "const-correctness" where code could promise to behave with proper semantics even when it looked "suspicious", but any problems which resulted would be the fault of the programmer breaking his promise, that would be a significant advantage over the status quo.

5
  • lol and so const poisoning spreads to Java (good answer, btw +1)
    – sea-rob
    Feb 26, 2014 at 21:05
  • 1
    @RobY: If one has a reference to a potentially-mutable value-holding object one isn't allowed to modify, and one would like to pass its state to a method which can't promise not to modify it, one must make a defensive copy of the object's state and pass that; that requirement will exist whether or not the reference is declared const. For const to really work, it needs to be applicable as a generic type trait (to allow generic wrappers to be able to pass non-const references to non-const arguments, and const ones to const arguments), but provided the type system handles it properly...
    – supercat
    Feb 27, 2014 at 19:35
  • 1
    ...the main thing const would do is require that promises that programmers are relying upon must be declaratively specified. While it's possible to produce constructs which even a good type system could not statically verify even though they would work in practice, code which passes an object which must never be modified to a method which sometimes modifies passed-in objects, but [fingers crossed] won't modify that one, is treading on thin ice.
    – supercat
    Feb 27, 2014 at 19:38
  • 1
    "const poisoning" is an informal term in C where you label something const, and that forces the callers to be const... etc. One "const" can cause you to touch like 66% of your files in a project ;) I just thought it was funny that const poisoning is on the verge of jumping all the way from C to Java. (I'm not saying I object, I just thought it was funny.)
    – sea-rob
    Feb 27, 2014 at 19:40
  • 1
    @RobY: I don't think it's anywhere near jumping; I would like to see a language/framework that could achieve the benefits without the costs, but to get maximal benefit it needs to be included from the start. I hope whoever designs "the next great framework" includes a type system which can distinguish whether a reference is being used to identify an entity, or encapsulate a mutable value which it owns, a mutable value owned by the owner of the reference holder, a potentially-shared value of potentially-mutable type which must never be mutated, etc.
    – supercat
    Feb 27, 2014 at 19:56
5

Not java, but I would recommend reading Eric Lippert's articles about immutability. This issue isn't as clear cut as you might think for java. There is no inherent performance impact in choosing one over the other, although it can impact performance depending upon your exact usage.

The key concept is whether and how an object can be changed.

3
  • 2
    The main reason to use immutable objects is thread safety - potential performance hits due to extra object allocations can be more than offset by the fact that you don't need to synchronise your code any longer...
    – assylias
    Oct 11, 2013 at 22:48
  • 1
    @assylias - Don't forget that immutable objects can be used freely in the construction of new instances so the cost of allocations can be mitigated in many cases. Oct 11, 2013 at 23:09
  • 2
    @assylias Considering how hard it is to get multithreading right, I'd argue the main reason for immutable objects is actually that they're easier to reason about.
    – Doval
    Feb 24, 2014 at 13:40
3

mutable - liable to change.

immutable - unchanging over time or unable to be changed.

Ok so we have the definitions. We know exactly what the words mean but how do they apply to programming? Let us move on to two new definitions.

mutable object - an object that is liable to change.

immutable object - an object that is unchanging over time or unable to be changed.

We can directly use the original definition when we put it in terms of object oriented programming. The final question is how do I use this in practice?

An immutable object must be initialized upon construction and rely only upon other immutable objects once initialized.

3

I would like to give a more clear picture on understanding the concept of Mutable and immutable class.
Mutable means whose value can be changed reverse is true for Immutable as already told.
Actually whenever you are calling constructor of any class we are actually allocating a memory space of that type of variable in heap. for e.g

String str1 = new String("john");
String str2 = str1 ;
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());

Here as I have called constructor of string class a memory is allocated for this variable with value as "john" and its reference code is returned to str1 varible. In the very next statement str2 is also made pointing to the same memory location.The two println statement will output the same value indicating that both variable is pointing to same memory location. Now write this code

str2 = "monk";
System.out.println(str2.hashCode());

The moment you write this line a new memory space for string type data is created in heap ,its value is set to "monk" and the reference of the same is returned to str2 and hence str2 is no more pointing to same memory location and hence you will get different hashcode value in println statement. The reason for this is "String is immutable class". So you can not change its value by any means. For StringBuffer Class you can check its mutability using this code

StringBuffer sb = new StringBuffer("mohan");    
StringBuffer sb1 = sb.append(" kumar");
System.out.println(sb.hashCode());
System.out.println(sb1.hashCode()+" - "+(sb1==sb)+" - "+sb.hashCode());
1
  • If the memory allocated in heap is of immutable type then the value hold by that memory allocation cant be changed.Like in the above example when we write str2 = "monk", it gives a impression that the value hold by memory allocation has changed. But it is not the case as explained above as the variable is of type immutable. Mar 11, 2015 at 9:38
0

Used in terms of primitives (built in type), and objects (user defined type). Immutable means you can't change the value. Mutable means you can change the value.

Many think primitive variables and object variables having a final modifier in front of them are immutable, however, this isn't exactly true. Final almost doesn't mean immutable for variables. Check out this link for a code sample http://www.siteconsortium.com/h/D0000F.php.

1
  • 1
    I mean objects aren't built in types and primitives are
    – Jon
    Jan 1, 2014 at 6:17
0

Take the following code example (this is C# but the same principle applies)

public void MyMethod()
{
    var person = new Person("Bob");
    Console.WriteLine("1 " + person.Name);

    SomeOtherClass.SomeMysteryMethod(person);
    Console.WriteLine("2 " + person.Name);

    person = SomeOtherClass.SomeOtherMysteryMethod(person);
    Console.WriteLine("3 " + person.Name);
}

What will be printed to the console in these lines? 1 will clearly print Bob, no doubt about that. But what about 2?

If Person is mutable, then you can't answer this question with any certainty. SomeMysteryMethod may have changed the person.Name. The Person class clearly makes it possible to do so, since that what it means to be mutable. Maybe 2 will print a different name, maybe it will print the same name.

If Person is immutable, that means that it inherently made it impossible to change person.Name (after the constructor has finished). This means that you can say for a fact that 2 will still print Bob.

However, that expectation goes out the door with 3. Immutability only means that a specific instance cannot be changed. However, it's possible that SomeOtherMysteryMethod returned a completely different instance of a Person, and that different instance can have a completely different value for its Name property.
In other words, you can never be sure what 3 will return, regardless of Person being mutable or immutable.

0

An instance is immutable if you cannot change it. Strings in Objective-C cannot be changed. But that's not a part of the language, it's the simple fact that the NSString class has no methods that could change an NSString instance. I think there is nothing in the implementation of NSString that would make it hard to add such a method (in the standard library), but of course that would be missing the point; there are good reasons why we want NSString instances to be immutable.

In C++ there is a distinction between "logically immutable" and "formally immutable". A class can have "mutable" members. Say I have a "Person" class that takes its data from a database, but caches them. So if the name in the database is "John Smith", that is the logical name. The first time you call the name() method it reads "John Smith" from the database and caches the name. The logical name hasn't changed, even though the actual C++ object has changed. We consider this to be immutable. But then C++ says that an instance is immutable if it is declared as "const". If an instance is accessed through a "const*" or "const&", that doesn't mean the instance is immutable, it only means that you are not allowed to modify the instance by using that pointer (and it is very naughty but not illegal to modify it through other means).

In Swift, there are "value" objects and "reference" objects. And variables are modifiable or not. If an unmodifiable variable contains a reference to an object, then the reference cannot be changed (it will always refer to the same object), but the referenced object can be changed. If an unmodifiable variable contains a value object, then the object cannot be changed. Assigning the variable to another variable creates a copy of the value object, which has its own independent value that may or may not be modified.

So all in all, "mutable" vs. "immutable" has many different meanings. Roughly it means you can more rely on immutable objects not changing; details depend on the language.

PS. Hashcode and "equals" were mentioned elsewhere. If you use an item as a dictionary key or set element, you really really don't want the hash code to change. And you don't want the fact that two keys are equal or different to change. Being immutable helps, but isn't necessary. You can have mutable objects where only things that affect "hashcode" and "equals" cannot be modified.

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