what is the sense of final ArrayList?

JavaArraylistFinal

Java Problem Overview


Which advantages/disadvantages we can get by making ArrayList (or other Collection) final? I still can add to ArrayList new elements, remove elements and update it. But what is effect making it's final?

Java Solutions


Solution 1 - Java

> But what is effect making it's final?

This means that you cannot rebind the variable to point to a different collection instance:

final List<Integer> list = new ArrayList<Integer>();
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile

As a matter of style, I declare most references that I don't intend to change as final.

> I still can add to ArrayList new elements, remove elements and update it.

If you wish, you can prevent insertion, removal etc by using Collections.unmodifiableList():

final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...));

Solution 2 - Java

It just means that you can't re-assign its reference. Attempting to do something like the below will lead to compiler error.

final List<String> list = new ArrayList<String>();

list = new LinkedList<String>();
     ^
     Compiler error here

If you really want an immutable list, you should use the Collections.unmodifiableList() method.

Solution 3 - Java

You won't be able to modify its reference using new ArrayList for example.

Solution 4 - Java

Making the variable final makes sure you cannot re-assign that objest reference after it is assigned. As you mention you can still use that lists methods to make changes.

If you combine the final keyword with the use of Collections.unmodifiableList, you ge the behaviour you are probably trying to achieve, for instance:

final List fixedList = Collections.unmodifiableList(someList);

This has as result that the list pointed to by fixedList cannot be changed. Beware however that it can still be change through the someList reference (so make sure it is out of scope after this asignment.)

Solution 5 - Java

final has a lot of consequences under multi threading.

  1. JMM clearly defines a final field's initialization completion is guaranteed.

What's not clearly defined is:

  1. Compilers are free to reorder them across memory barriers.
  2. Compilers can always read a cached copy.

Solution 6 - Java

It doesn't effect what you can do with the ArrayList as you rightfully observe - the ArrayList itself is still mutable. You have just made the reference immutable.

But making a variable final does have other benefits:

  • It prevents the variable from being changed if it is expected to stay constant. This can help prevent future bugs.
  • Making variables final can help the compiler make certain performance optimisations.

In general, the more things that you make immutable, the better. So making references final (even if they are references to mutable objects) is generally a good idea.

Solution 7 - Java

> Final is a keyword or reserved word in java and can be applied to > member variables, methods, class and local variables in Java. Once you > make a reference final you are not allowed to change that reference > and compiler will verify this and raise compilation error if you try > to re-initialized final variables in java.

Solution 8 - Java

You cannot rebind it to a different collection as aix said.

Example: In conjuction with immutable list implementation you get safe members which you can make public available.

Example: When you rely on that reference does not change you need final. This is true in synchronization scenarios for example.

There may be much more examples. It is good style to declare members final if you do not intend to change the reference at all.

Solution 9 - Java

I personally mark the collections field of my classes as final to save the users of my class from checking whether it is null or not. This works because, once the value is already assigned to a final variable, it can never be reassigned to another value, including null.

Solution 10 - Java

To get a really immutable list, you will have to make deep copies of the contents of the list. UnmodifiableList would only render the list of references somewhat immutable. Now making a deep copy of the List or array will be tough on memory with the growing size. You can make use of serialization/deserialization and store the deep copy of array/list into a temp file. The setter would not be available as the member varaible needs to be immutable. The getter would serialize the member variable into a file and then desialize it to get a deep copy. Seraialization has an innate nature of going into the depths of an object tree. This would ensure complete immutability at some performance cost though.

 package com.home.immutable.serial;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public final class ImmutableBySerial {
	
	private final int num;
	private final String str;
	private final ArrayList<TestObjSerial> immutableList;
	
	ImmutableBySerial(int num, String str, ArrayList<TestObjSerial> list){
		this.num = num;
		this.str = str;
		this.immutableList = getDeepCloned(list);
	}
	
	public int getNum(){
		return num;
	}
	
	public String getStr(){
		return str;
	}
	
	public ArrayList<TestObjSerial> getImmutableList(){
		return getDeepCloned(immutableList);
	}
	
	private ArrayList<TestObjSerial> getDeepCloned(ArrayList<TestObjSerial> list){
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		ArrayList<TestObjSerial> clonedObj = null;
		try {
			 fos = new FileOutputStream(new File("temp"));
			 oos = new ObjectOutputStream(fos);
			 oos.writeObject(list);
			 fis = new FileInputStream(new File("temp"));
			 ois = new ObjectInputStream(fis);
			 clonedObj = (ArrayList<TestObjSerial>)ois.readObject();
			 
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				oos.close();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return clonedObj;
	}
}

Solution 11 - Java

Essentially what you are trying to achieve here is making the list immutable I guess. However when you mark the list reference final it implies that the reference cant be pointed to any other list object other than this.

If you want a final (immutable) ArrayList go for Collections class's utility method Collections.unmodifaibleList( list ) instead.

Solution 12 - Java

I came to think of this same question and coded and example to add to the explanation from yet another angle.

> The final arrayList can still be modified, refer to the example below and run it to see for your self.

Here is the immutable class with immutable List declaration:

public final class ImmutableClassWithArrayList {
 final List<String> theFinalListVar = new ArrayList<String>();
}

And here is the driver:

public class ImmutableClassWithArrayListTester {
public static void main(String[] args) {
	ImmutableClassWithArrayList immClass = new ImmutableClassWithArrayList();
	immClass.theFinalListVar.add("name");
	immClass.theFinalListVar.forEach(str -> System.out.println(str));
 }
}

> As you can see, the main method is adding (modifying) the list. So the only thing to note is that the "reference" to the object of the collection type can't be re-assigned to another such object. As in the answer by adarshr above, you can't do immClass.theFinalListVar = new ArrayList(); in the main method here.

The modification part really helped me understand this and hope it helps in same way.

Solution 13 - Java

If We declare ArrayList as final we can still add elements to it but we can't reassign it.

final ArrayList<String> list = new ArrayList<>();
        list.add("abc"); //allowed
        list.add("pqr"); //allowed

list = new ArrayList<>(); // Not allowed

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWelcomeToView Question on Stackoverflow
Solution 1 - JavaNPEView Answer on Stackoverflow
Solution 2 - JavaadarshrView Answer on Stackoverflow
Solution 3 - JavaMichael LaffargueView Answer on Stackoverflow
Solution 4 - JavarspView Answer on Stackoverflow
Solution 5 - Javauser6765777View Answer on Stackoverflow
Solution 6 - JavamikeraView Answer on Stackoverflow
Solution 7 - JavalfergonView Answer on Stackoverflow
Solution 8 - JavaFabian BarneyView Answer on Stackoverflow
Solution 9 - JavaBnrdoView Answer on Stackoverflow
Solution 10 - JavaRajeev RanjanView Answer on Stackoverflow
Solution 11 - JavaAdwivediView Answer on Stackoverflow
Solution 12 - JavaNirmalView Answer on Stackoverflow
Solution 13 - Javashubh gaikwadView Answer on Stackoverflow