If you really meant List#of
methods, read the correct Answer by saka1029. If you actually meant List#copyOf
, read this Answer.
Instantiate fresh new list before calling Collections.unmodifiableList
You are correct about Collections.unmodifiableList
returning an object that is merely a view onto the original. So if the original changes, so too does the not-so-unmodifiable list.
The solution is simple: Copy the list into a new fresh list before passing to Collections.unmodifiableList
.
List< Whatever > tempList = new ArrayList<>( myOriginalList ) ; // Passing a collection to constructor of `ArrayList` creates an entirely new fresh list copied from the original.
List< Whatever > unmodifiableList = Collections.unmodifiableList( tempList ) ;
Be sure you never expose that tempList
to any other code, so its contents are never manipulated. Or, better yet, use a single-line to make such sharing impossible.
List< Whatever > unmodifiableList = Collections.unmodifiableList( new ArrayList<>( myOriginalList ) ) ;
Being strict
To truly replicate the behavior of List#copyOf
, you would check to see if the original list is already unmodifiable. If so, no action is taken. The original list is returned as the result of the method call. Quoting the Javadoc:
If the given Collection is an unmodifiable List, calling copyOf will generally not create a copy.
You should also do some null checks. Quoting the Javadoc:
The given Collection must not be null, and it must not contain any null elements.
Lastly, I will add a friendly suggestion that you consider upgrading past Java 8. Many wonderful new features have been added in the intervening years. Currently Java 16 is the latest release, with Java 17 this fall (2021-09-14) likely to be designated an LTS version.