Unlike Collections.unmodifiableList(java.util.List extends T>), which is a view of a
separate collection that can still change, an instance of ImmutableList contains its own private data and will never change.
ImmutableList is convenient for public static final lists
("constant lists") and also lets you easily make a "defensive copy" of a list
provided to your class by a caller.

Note: Although this class is not final, it cannot be subclassed as
it has no public or protected constructors. Thus, instances of this type are
guaranteed to be immutable.

of

Returns an immutable list containing a single element. This list behaves
and performs comparably to Collections.singleton(T), but will not
accept a null element. It is preferable mainly for consistency and
maintainability of your code.

copyOf

Returns an immutable list containing the given elements, in order. If
elements is a Collection, this method behaves exactly as
copyOf(Collection); otherwise, it behaves exactly as copyOf(elements.iterator().

copyOf

Despite the method name, this method attempts to avoid actually copying
the data when it is safe to do so. The exact circumstances under which a
copy will or will not be performed are undocumented and subject to change.

Note that if list is a List<String>, then ImmutableList.copyOf(list) returns an ImmutableList<String>
containing each of the strings in list, while
ImmutableList.of(list)} returns an ImmutableList<List<String>>
containing one element (the given list itself).

This method is safe to use even when elements is a synchronized
or concurrent collection that is currently being modified by another
thread.