18
final Integer[] arr={1,2,3};
arr[0]=3;
System.out.println(Arrays.toString(arr));

I tried the above code to see whether a final array's variables can be reassigned[ans:it can be].I understand that by a final Integer[] array it means we cannot assign another instance of Integer[] apart from the one we have assigned initially.I would like to know if whether it is possible to make the array variables also unmodifiable.

ZoogieZork
  • 11,215
  • 5
  • 45
  • 42
Emil
  • 13,577
  • 18
  • 69
  • 108
  • 3
    The only way to make arr unmodifiable is to take a clone or copy of it and use the copy. That way the original won't be changed. BTW: int[] may be a better choice than Integer[] here. – Peter Lawrey Sep 17 '10 at 20:11
  • Check my answer here http://stackoverflow.com/a/16545097/326874 – æ-ra-code May 14 '13 at 13:53

7 Answers7

30

This isn't possible as far as I know.

There is however a method Collections.unmodifiableList(..) which creates an unmodifiable view of e.g. a List<Integer>.

If you want to guarantee that not even the creator of the unmodifiable view list will be able to modify the underlying (modifiable) list, have a look at Guava's ImmutableList.

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239
Andre Holzner
  • 18,333
  • 6
  • 54
  • 63
  • 4
    This is another good reason to use collections instead of arrays. – Skip Head Sep 17 '10 at 18:06
  • 3
    @SkipHead Depends for which target you are programming. Not every Java program runs in a Java EE container on some large mainframe. – Martin Apr 28 '13 at 15:49
  • See the latest documentation of Guava's ImmutableList at http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/index.html as add and addAll methods are now deprecated. – Mohamed El-Nakeep Mar 08 '14 at 18:25
10

No. The contents of an array can be changed. You can't prevent that.

Collections has various methods for creating unmodifiable collections, but arrays aren't provided for.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
6

The final keyword only prevents changing the arr reference, i.e. you can't do:

final int[] arr={1,2,3}; 
arr = new int[5]; 

If the object arr is referring to is mutable object (like arrays), nothing prevents you from modifying it.

The only solution is to use immutable objects.

Ssancho
  • 149
  • 1
  • 2
2

Another way is to use this function:

Arrays.copyOf(arr, arr.length);
xyz
  • 812
  • 9
  • 18
  • 1
    However, that would introduce extra overhead (stored twice in memory) as the entire array is copied again. – tokovach Nov 25 '20 at 13:17
1

I'd go with List.of(array), as available from Java 9 on, which creates a copy of the source array internally and an immutable List from that. Note though, there there're no null values allowed in this implementation.

If this is a requirement, Arrays.copyOf([T]source, int length) can be used, if no real immutability is needed, but only the source array mustn't be modified.

Otherwise, if immutability of the target Collection is required, Java's immutable Collection API or Guava might be your best shot e. g. Collections.immutableXX() or ImmutableList.of().

If additional dependencies are not desired, one of the following approaches should work, depending on, whether further pre-processing is needed, before making the result immutable:

final T[] objects = (T[])new Object[] { null };
final T obj = (T)new Object();

final BinaryOperator<ArrayList<T>> listCombiner = (a,b) -> { a.addAll(b); return a; };
final Collector<T, ArrayList<T>, List<T>> collector = Collector.of(
  ArrayList<T>::new, List::add, listCombiner, Collections::unmodifiableList
);

final List<T> list = Arrays.stream(objects).collect(collector);

or simply

final List<T> list = Collections.unmodifiableList(Arrays.asList(objects ));

Edit: As already outlined, creating an immutable array in itself is not possible in Java.

fozzybear
  • 91
  • 9
  • Defintely the best way as both are wrapper, and avoids copying the array. The copy itself is cheap thouhg, but attempts to modify it might still happen. – mjs Mar 04 '23 at 18:59
0

To anybody else reading this old question, keep in mind there is also Google Guava's immutable collections. ImmutableList has much stronger performance than Collections.unmodifiableList(), and is arguably safer as it truly is immutable,and not backed by a mutable collection.

tmn
  • 11,121
  • 15
  • 56
  • 112
0

The keyword 'final' applies to only the references (pointer to the memory location of the object in the heap). You can't change the memory address (location) of the object. Its upto your object how it internally handles the immutability.

Added, although int is a primitive data type int[] should be treated as a object.

You can't do this

final int a = 5
a = 6

You can do this:

final int[] a = new int[]{2,3,4};
  a[0] = 6;

You can't do this:

final int[] a = new int[]{2,3,4};
 a = new int[]{1,2,3}
Rajendra
  • 1,703
  • 2
  • 16
  • 22