15

Why won't declaring an array final make it immutable in Java? Doesn't declaring something final mean it can't be changed?

From question related to immutable array it's clear that declaring an array final doesn't make it unchangeable.

The following is possible.

final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;

My question is: What is the function of declaring final here then?

Community
  • 1
  • 1
nayef
  • 408
  • 2
  • 4
  • 10
  • 2
    http://stackoverflow.com/questions/10339930/final-array-in-java – lbalazscs Dec 20 '12 at 20:14
  • While many answers talk about references [to objects], I like to simply say that `final` is *only* an attribute of the *variable/field* and has nothing to do with the *object/value* that variable/field evaluates to. Variables/fields and objects/values are different things. Only the former are affected by the modifier. –  Dec 20 '12 at 20:17

6 Answers6

33

final is only about the reference that is marked by it; there is no such thing as an immutable array in Java. When you say

private final int[] xs = new int[20];

you won't be allowed to say

xs = new int[10];

later on. That's all what final is about. More generally, ensuring that an object is immutable is often hard work and full of a range of subtleties. The language itself doesn't give much to this end out of the box.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 2
    However, there are immutable collections. ([`Collections.emptyList()`](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#emptyList%28%29) and [`Collections.unmodifiableList(List extends T>)`](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableList%28java.util.List%29) for instance) – Powerlord Dec 20 '12 at 20:12
  • 1
    @Powerlord `Collections.emptyList()` is a better example; `Collections.unmodifiableList()` is just a wrapper and the underlying list can still be changed anytime. – Marko Topolnik Dec 20 '12 at 20:16
  • 1
    `Collections.EMPTY_LIST` isn't Generic, which is why `.emptyList()` exists. – Powerlord Dec 20 '12 at 20:16
  • @Powerlord - but that is beside the point ... which is immutablility, and how it is implemented in Java. – Stephen C Dec 20 '12 at 20:19
  • Just to be pedantic, you _can_ create an immutable array in Java. `new int[0]`. :) – yshavit Dec 20 '12 at 20:48
  • One potential difference here is that, IIRC, the final modifier *DOES* have semantics with regard to the Java Memory Model. Consider if the type of array was not `int`, but was some object type, `final` would guarantee that all array elements would be fully initialised before any other thread sees a reference to them. I don't have JCIP to hand to confirm, unfortunately. – Grundlefleck Dec 20 '12 at 22:53
  • 2
    @Grundlefleck Don't need JCIP, you can get it [from the horse's mouth](http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5). Of course, those semantics are only valid if you don't leak that field or `this` from the constructor, and if you ever modify the array (including modifying one of its object, if it's an array of reference types) after the constructor returns, all bets are off. – yshavit Dec 20 '12 at 22:58
8

final means you can't change the reference - ie you can't assign another array to that field.

"Immutable" means you can't change the contents of the array - final has no effect on that.

As your code shows, you can assign a value to one of the elements of the array, which doesn't change the reference to the array

Bohemian
  • 412,405
  • 93
  • 575
  • 722
3

Here you are making a object reference final, not a primitive. (Arrays are special Java objects, too.) Making a reference final means that you cannot make it refer something else once it is initialized. But of course you can change the state of an object referred by a final variable.

Juvanis
  • 25,802
  • 5
  • 69
  • 87
1

declaring an array

In Java, we declare variables, and create objects (such as arrays). These actions are independent; we can declare a variable without creating an object, and create an object without declaring a variable.

Immutability is a property of an object, while final is a property of a variable. An object may be referred to by several variables. Which variable should govern immutability of the array object?

int[] a = {1,2,3};
final int[] b = a;
a[0] = 10; // should this be legal?

If we permit this, the supposedly immutable value of b[0] has been changed. But how can the compiler prevent this? By making it impossible to assign a non-final to a final reference? How would I initialize the array, then? I couldn't do so in a loop ...

And: What does it even mean for an array to be immutable? For instance, should the following compile?

final int[][] a = {{1,2}, {3,4}};
a[1][1] = 5;

C++ solves this by permitting const to be specified (or omitted) for each level of indirection. In Java, final can be specified (or omitted) once per variable. Yes, final is a simpler const, much like Java is a simpler C++. Let's keep it simple, shall we?

meriton
  • 68,356
  • 14
  • 108
  • 175
  • I consider the inability to specify attributes at different levels of indirection to be a major limitation of Java, since there is a fundamental difference between an `int[]` which encapsulates a sequence of numbers as a non-sharable reference to an array the owner may change, an `int[]` which encapsulates a sequence of numbers as a sharable reference to an array which all holders agree never to change, and an `int[]` which *identifies* an array owned by some other entity. One wouldn't need to worry about "deep" versus "shallow" cloning or equality if the type system made such distinctions. – supercat Nov 20 '13 at 23:15
  • With regard to your example, the Java array declaration syntax makes it unclear how to apply attributes to layers. If declarations were more of a generic style: `final ImmutableArray> a = {...}` things would be much clearer. An `ImmutableArray` or an `Array` could be implicitly converted to a `ReadableArray`, though not vice versa. Code which held a `ReadableArray` reference could try to cast it to a `MutableArray`, succeeding at run-time only if the type was actually mutable. – supercat Nov 20 '13 at 23:24
  • 1
    @supercat: If you feel this strongly about this, you're free to create an ImmutableArray wrapper class around an array that enforces the semantics you want. Or you might use [`ImmutableList`](http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableList.html). I therefore disagree that a lack of const for array types is a major limitation of java. At most, it is a limitation of Java *arrays* with an easy workaround. – meriton Nov 21 '13 at 17:49
0

It means that a new instance of the object would not be allowed.

Zafer
  • 21
  • 4
0

Like everyone commented, declaring it final will not let you assign another array to your variable. Read more here

The array itself will retain it's properties same as before.

Steve Kuo
  • 61,876
  • 75
  • 195
  • 257
Farhan Syed
  • 336
  • 3
  • 15