1

I'm confused on the concept of "being immutable". Our professor is saying "ints are immutable! Strings are immutable" everyday, what does he mean by that exactly?

A more general question, how do we know if a data structure is immutable or not?

Thanks

  • 4
    Wait, who's trying to say that `int`s are immutable, and in what language? –  Apr 09 '13 at 23:41
  • 1
    strings are immutable, you mean Java right? – taocp Apr 09 '13 at 23:42
  • http://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html – Oliver Charlesworth Apr 09 '13 at 23:43
  • see this post? http://stackoverflow.com/questions/5560176/is-integer-immutable – taocp Apr 09 '13 at 23:44
  • could be Python as well – Eevee Apr 09 '13 at 23:47
  • our class is consist of java and c++ at the same time, I'm not sure which one he's talking about. Is there any difference? – Ruoxing Sun Apr 09 '13 at 23:50
  • 1
    `int`s aren't immutable, but if you wrap them in an `Integer`-object like this: `Integer i = new Integer(123)`, then those objects are immutable. This means you can't change an `Integer`-object once created, for instance by calling `setValue`, since it has no such method. EDIT: This comment was about Java. – Lone nebula Apr 10 '13 at 00:00

9 Answers9

7

Some of the other answers here are confusing mutability/immutability with value/reference semantics, so be careful...


Simply put, an entity is mutable if it may be modified after it's been created. In other words, its value may change over time.

First, a counterexample. A Java String object is immutable; there is no method that you can call on a String object that will change its value:

String a = "foo";
a.concat("bar");
System.out.println(a);  // foo

You could do this instead:

String a = "foo";
a = a.concat("bar");
System.out.println(a);  // foobar

but that works because concat() is creating a new String object, and the reference a is then repointed at it. There are now two String objects; the original has not changed (it's just lost forever). a is mutable, the underlying object isn't.


As for int variables; in C or Java, we can do this:

int x = 3;
x = 4;  // Mutates x
x++;    // Mutates x

How do we know these really mutate x, rather than simply creating a new integer "object" and "repointing" x at it? (Other than by the fact that the language assures us that primitive types are distinct from object types.) In C, we can somewhat prove it:

int x = 3;
int *p = x;   // Pointer to original entity
x = 4;
printf("%d\n", *p);   // 4

AFAIK, there is no equivalent approach in Java. So you could argue that the question of whether integer types are truly mutable in Java is irrelevant.


As for how we know whether a given type is immutable, very often we don't. At least, not without inspecting it, or simply believing a promise we've been told.

In Java, ensuring a user-defined type is immutable involves following a few simple rules (explained here). But it's still just a promise; the language doesn't enforce it.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

Immutability (of an object or value, not a variable) usually means there's no way to do an in-place change of the value. (One that would propagate to other references to it.) This means that if you have something like the following:

String a = "foo";

There is no operation that you could perform on a that would change its value. I.e. you can't have a hypothetical method append() that would cause the following behaviour:

String a = "foo";
a.append("bar"); // a is not reassigned
System.out.println(a); // prints "foobar"

You can contrast this with mutable objects like collections:

int[] as = new String[] { "foo" };
as[0] = "bar"; // we're changing `as` in-place - not the Strings stored in it
System.out.println(as[0]); // prints "bar"

Primitive types are not a great choice of example for Java, since you can't have multiple references to them, and there's no way to demonstrate the distinction between a mutation and a reassignment.

millimoose
  • 39,073
  • 9
  • 82
  • 134
  • Huh? Isn't that more about reference semantics than immutability? – Oliver Charlesworth Apr 09 '13 at 23:47
  • @OliCharlesworth I'm not sure those can be completely divorced in the context Java. You might as well start asking me to define "value". Or maybe `int`s are a bad example in this case since Java doesn't permit multiple references to one. – millimoose Apr 09 '13 at 23:52
  • They can definitely be divorced! The only way that any operation on `a` could cause observable changes in `b` is if `b` is an alias/reference to `a`. That has nothing to do with immutability. – Oliver Charlesworth Apr 09 '13 at 23:53
  • @OliCharlesworth Right, so it doesn't really make sense to talk about immutability of `int`s in the first place. I'll rework the answer to use `String`s as a better example. – millimoose Apr 09 '13 at 23:54
  • I think this answer is more like an example of pointers and references – Ruoxing Sun Apr 09 '13 at 23:55
  • Ok, I now see what your answer is getting at. But still, the second variable confuses things. You could get rid of `b` entirely, print `a` instead, and things would be clearer. – Oliver Charlesworth Apr 09 '13 at 23:58
  • @RuoxingSun You're asking for the definition of "immutable", I'm providing the one that makes sense in the context of Java. There, as Oli points out, it doesn't make sense to talk about an object's immutability if there aren't multiple references to it. (In C++, things get *way* more complex.) – millimoose Apr 10 '13 at 00:00
  • @millimoose: It **does** make sense to talk about immutability in the case of a single reference... – Oliver Charlesworth Apr 10 '13 at 00:01
  • @OliCharlesworth I don't know. With only a single variable involved, there's no way to distinguish between an object being mutated and the variable being reassigned. The object can certainly be immutable, I'm just not sure how to demonstrate this with an example, as opposed to describe it in prose. – millimoose Apr 10 '13 at 00:01
  • @millimoose: `String a = "foo"; a.append("bar"); System.out.println(a);`. `"foo"` implies that `a` is not mutated. `"foobar"` implies that `a` has been mutated. – Oliver Charlesworth Apr 10 '13 at 00:03
  • @OliCharlesworth Right, I guess I just wanted to emphasise that `b` is never being reassigned (or at all touched) after the mutation. – millimoose Apr 10 '13 at 00:08
1

What is immutable is highly language-dependent, but an immutable object is simply an object that cannot be changed after it is created.

What this usually means is that:

int x = 4;
x = 5;//not 'allowed'

This is seen in languages where primitives, such as an int, can be immutable (such as functional languages like Scala).

Most objects in OOP are actually pointers to a place in memory. If that object is immutable that location in memory cannot have its contents changed. In the case of a String in Java, we see this happening:

String a = "Hello"; //points to some memory location, lets say '0x00001'
a = a + " World!"; //points to a new locations, lets say '0x00002'
System.out.println(a);//prints the contents of memory location '0x00002'

In this case, a actually points to an entirely different place in memory after line 2. What this means is that another thread with a different scope that has handed a would not see "Hello World!" but instead "Hello":

String a = "Hello";
startThread(a, " Hello!");//starts some thread and passes a to it
startThread(b, " World!");//starts another thread and passes a to it

   ...

public void methodInThread(String a, String b) {
  a = a + b;
  System.out.println(a);
}

These two threads will output the following, regardless of the order they're called in:

"Hello Hello!" //thread 1
"Hello World!" //thread 2
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
  • 1
    Seriously though.. is there a language where integral types are immnutable? That seems awfully stupid. – Simon Whitehead Apr 09 '13 at 23:44
  • I thought the distinction wasn't that you can't set a new value to `x`, just that when you do it is a new object. – Jason Sperske Apr 09 '13 at 23:45
  • @SimonWhitehead: I don't know. But there are many C programmers who often claim that they would like `const` to be the default... – Oliver Charlesworth Apr 09 '13 at 23:45
  • 3
    In most languages, `x` isn't immutable, but `4` certainly is. In a language where `x` is conceptually a reference to an `int` object, assigning a value to `x` doesn't change the value of some other object (or reference) that's been initialized to `x`. – Keith Thompson Apr 09 '13 at 23:46
  • Maybe we're talking about an "everyting is an object" language where it's more like x = Int(4). x is a pointer that can change. Int(4) has no methods to modify it's value. ?? – Julian Apr 09 '13 at 23:46
  • @SimonWhitehead In the sense of not being assignable, most functional languages. In java, calling `int`s immutable makes sense because you, in fact, can't mutate them - you can only perform assignments. – Cubic Apr 09 '13 at 23:47
  • @Cubic: In the case of Java primitives, an assignment very definitely causes mutation! Unless you're suggesting that in something like `int a = 3; a = 4;`, the second `a` is actually a different instance. At which point this all starts getting a bit philosophical... – Oliver Charlesworth Apr 09 '13 at 23:49
  • This veers into vague definition territory. Immutable/constant variables and immutable/constant objects are different if related concepts, and there's probably loads of debate whether one should imply the other. C++ has language-level support for *both*, the latter can be enforced in class design, and it's easy to conflate things in this territory. – millimoose Apr 09 '13 at 23:50
  • @OliCharlesworth Depends on how you define mutation. There's no operation to make the integer 4 become the integer 5, there are only operations that make a variable holding the integer 4 hold the integer 5 instead. – Cubic Apr 09 '13 at 23:50
  • 2
    @Cubic: Ah you're talking about literals. Generally when we talk of "an `int`", we mean "a variable of type `int`"... – Oliver Charlesworth Apr 09 '13 at 23:51
  • For the record, the example given was on the assumption `int` is immutable and that the hypothetical compiler will cause an error if you try to reassign it. – Nathaniel Ford Apr 09 '13 at 23:54
  • 1
    `const` and `immutable` are different things. I think your answer is actually a tad confusing. – Simon Whitehead Apr 10 '13 at 00:00
  • Sorry, have to -1 this. All that stuff about "a new place in memory is allocated, 5 is placed in that location, and the variable x is pointed to that location" is nonsense! At least in C-like languages (including Java). Unless of course, that's supposed to be a description of what a hypothetical language with immutable ints might do. But that's not made clear at all! – Oliver Charlesworth Apr 10 '13 at 00:10
  • Yeah, I got into my own head there. Excised that part. – Nathaniel Ford Apr 10 '13 at 00:44
1

It's awkward to talk about immutability of ints, because the idea of mutating something that isn't a container doesn't make sense to most of us. So let's talk about strings.

Here's a string, in Python:

s = "abc"

Strings are containers in the sense that they contain some number of individual characters: here a, b, and c. If I want to change the second character to a d, I might try:

s[1] = 'd'

Which will fail with a TypeError. We say strings are immutable in Python because there is no operation that will alter an existing string. Certainly there are plenty of operations that will perform some operation and create a new string, but existing strings are set in stone.

There are a couple advantages here. One is that it allows interning: sometimes when a string needs allocating (and at the discretion of the interpreter), CPython will notice that an identical string has already been allocated and just reuse the same str object. This is easiest when strings are immutable—otherwise, you'd have to do something about problems like this:

s = "abc"
t = "abc"   # this reuses the same memory, as an optimization
s[0] = "x"  # oops!  now t has changed, too!

Interning is particularly useful in Python and similar languages that support runtime reflection: it has to know the name of every function and method at runtime, and a great many methods have builtin names like __init__ (the name of the constructor method), so reusing the same string object for all those identical names saves a good deal of wasted space.

The other advantage is in semantics: you can safely pass strings to arbitrary functions without worrying that they'll be changed in-place behind your back. Functional programmers appreciate this kind of thing.

The disadvantage, of course, is that doing a lot of work with very large strings requires reallocating and rebuilding those large strings many times over, instead of making small edits in-place.

Now, about ints. This is NOT an example of immutability:

x = 3
x = 4

This doesn't involve the actual objects at all; it only assigns a new value to the variable x.

Consider instead:

x = [1, 2, 3]
y = x
x[:] = [4, 5, 6]
print y  # [4, 5, 6]

The x[:] = syntax is "slice notation" for replacing the entire contents of a list. Here, x and y are two names for the same list. So when you replace the contents of x, you also see the same effect in y, because... they both name the same list. (This is different from reference variables in other languages: you can assign a new value to either x or y without affecting the other.)

Consider this with numbers. If you could do some hypothetical operation like the above on plain numbers, this would happen:

x = 3
y = x
x[:] = 4
print y  # hypothetically, 4

But you can't do that. You can't change the number an existing int represents. So we call them immutable.

Mutating an int is easy in Smalltalk:

3 become: 4

This would change the 3 to a 4, overwriting the memory that previously contained a 3. If ints are interned (as they can be in Python), this could even mean that everywhere 3 appears in your source code, it acts like the number 4.

In C, these distinctions aren't as meaningful, because variables are fixed blocks of memory rather than the transient labels of Python. So when you do this:

int x = 3;
x = 4;

It's hard to say definitively whether this is "mutating" an int. It does overwrite existing memory, but that's also just how C variable assignment works.

Anyway! Mutability is just about whether you're altering an existing object or replacing it with a new one. In Python and Java, you can't alter existing strings, and you can't "alter" numbers, so we call them immutable. You're free to change the contents of lists and arrays in-place without creating new ones, so they're mutable.

Eevee
  • 47,412
  • 11
  • 95
  • 127
  • +1 for using the concept of a "container". (Which can be a string, or an array, or a C++ pointer / memory address.) – millimoose Apr 10 '13 at 00:15
  • "the idea of mutating something that isn't a container doesn't make sense to most of us" - not really... – Oliver Charlesworth Apr 10 '13 at 00:15
  • Like many of the answers here, the stuff with `y = x`, etc. on `int` types seems to be conflating value/reference semantics with mutability/immutability... – Oliver Charlesworth Apr 10 '13 at 00:20
  • @OliCharlesworth i'm using Python as my example, which _does not have_ reference variables. i was under the impression that Java doesn't either. – Eevee Apr 10 '13 at 00:25
  • @Eevee: Your examples where you assign `x` to `y`, modify `x` and then print `y` are nothing to do with immutability. They're to do with whether the assignments are based on value or reference semantics. I don't know Python very well; it may not call that array-slicing thing a "reference", but it certainly acts like one. – Oliver Charlesworth Apr 10 '13 at 00:27
  • @OliCharlesworth *Assignment to* a Python list slice is an in-place change of the list. (Retrieving a slice creates a new list.) – millimoose Apr 10 '13 at 00:36
  • @millimoose: Right, so in this context it's effectively a reference/alias/view/pointer. – Oliver Charlesworth Apr 10 '13 at 00:37
  • @OliCharlesworth Kinda sorta. Under the hood it's just sugar for a mutator method, a "list slice" isn't a first-class concept. I suppose it's difficult to think about it conceptually if you know how it works. – millimoose Apr 10 '13 at 00:38
  • Also, I'm not sure whether the C-Python distinction as far as variables are concerned holds. Python certainly has stack frames with slots for local variables, and I'd say they're more similar than distinct to one another. (With the exception where C lets you take a pointer to a local variable easily, whereas in Python this would be kind of magical.) – millimoose Apr 10 '13 at 00:40
  • Instead of magical, I should've said "maybe impossible", at least none of the methods of open-brain surgery I've tried let me poke around in a caller's local variables. – millimoose Apr 10 '13 at 00:49
  • @OliCharlesworth Python doesn't really have _either_ value or reference semantics; it has object semantics, like Java. variable assignment will never cause an implicit copy, but it will also never affect the variable's previous value or any other variable. – Eevee Apr 10 '13 at 01:57
  • @OliCharlesworth the slice syntax in particular is equivalent to `x.__setslice__(slice(None, None), [4, 5, 6])`, much as all Python operators resolve to method calls—except for local variable assignment, which is a statement and not an operator. slice assignment asks _the object_ to mutate itself. the variables are utterly incidental and only serve to demonstrate the behavior. – Eevee Apr 10 '13 at 01:59
  • @millimoose Python's slots for locals are a CPython optimization; the semantics are that a variable name is just a label for some object, versus C where a variable is a preallocated bucket into which data is _copied_. the difference is subtle, but the two concepts are complete opposites (memory-centric vs value-centric) and thinking in Python's terms makes e.g. function passing make a lot more sense to C immigrants. or, if it helps, everything in Python is a pointer that's always forcibly deallocated for you :) – Eevee Apr 10 '13 at 02:04
  • @Eevee: But there is a copy, at least in the case of primitives. `x = 5; y = x;`; `y` is now a distinct variable from `x`, whose value has been copied. So clearly modifying `y` has no effect on `x`. In the case of the slice thing, apparently both `x` and `y` are names to the same underlying object. Modifying the underlying object through one modifies the view through the other. But neither of these examples has anything to do with immutability. (Although of course in both cases, immutability would prevent any modification.) – Oliver Charlesworth Apr 10 '13 at 12:42
  • @OliCharlesworth in Python, at least, that code results in `y` and `x` naming _the same_ `5` object. `y = x` does the same thing regardless of whether `x` happens to contain a number or a list or whatever else. which makes it the easiest way to demonstrate what mutability _does_, but only if you accept up-front that Python **never makes implicit copies**. ever! – Eevee Apr 10 '13 at 18:16
0

An object is considered immutable if its state cannot change after it is constructed.

source : http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

Martin V.
  • 3,560
  • 6
  • 31
  • 47
0

Typically it means you can't call a method on the type (int or whatever) that will change a

Sometimes people refer to value types as being immutable

//theres no way for this to be mutable but this is an example of a value type
int a = 5
int b = a;
b=9

a does not change unlike class types like

MyClass a = new MyClass
MyClass b = a
b.DoSomething()
//a is now changed
0

An immutable object is some thing that once instantiated can not be modified. If you have to modify, a new object will be created and pointed to the reference.

And ints are not immutable.

SunnyPenguin
  • 137
  • 4
  • 15
0

There are some classes in java which are immutable like String, All Wrapper Class ie. Integer, Float, Long etc.

For Example: Integer i=5; i=10; i=15;

When Integer i=5, here a new Integer object is created, then in the 2nd, i=10 rather assigning this value 10 to previously created object, a another new object is created and assign to i, and 3rd i=15 , here again new object is created and again is assigned to i.

Note: don't be confused with int with Integer. int is primitive type and Integer is wrapper class. All primitives are mutable.

CrawlingKid
  • 959
  • 5
  • 15
0

The concepts of mutability and immutability are only relevant for things to which code may hold a reference. If one holds a reference to something, and some immutable aspect of that thing's state is observed to have some value (or state), then as long as that reference exists, that aspect of the thing's state may always be observed to have the same value (state).

The String type in Java may reasonably be described as immutable, because code which has a reference to a string and observes that it contains the characters "Hello" may examine it at any time and will always observe that it contain those characters. By contrast, a Char[] might in one moment be observed to contain the letters "Hello" but at some later time be observed to contain the letters "Jello". Thus, a Char[] is considered mutable.

Because it is not possible to hold a direct reference to an int in Java, the concepts of mutability and immutability are not really applicable to that type. One can, however, hold a reference to an Integer, for which they are relevant. Any such reference that is observed to have a particular value will always have that same value. Thus, Integer is immutable. Note that while the concepts of mutability and immutability aren't really applicable to value types like int, they do share a useful aspect of immutable types: the state represented by a storage location (variable, field, or array element) of either a primitive type or an immutable type is guaranteed not to change except by overwriting that location with either a new value or a reference to a different immutable object.

supercat
  • 77,689
  • 9
  • 166
  • 211