In Java 9 we have convenience factory methods to create and instantiate immutable List, Set and Map.
However, it is unclear about the specific type of the returned object.
For ex:
List list = List.of("item1", "item2", "item3");
In this case which type of list is actually returned? Is it an ArrayList or a LinkedList or some other type of List?
The API documentation just mentions this line, without explicitly mentioning that its a LinkedList:
The order of elements in the list is the same as the order of the
provided arguments, or of the elements in the provided array.
The class returned by List.of
is one of the package-private static classes and therefore not part of the public API:
package java.util;
...
class ImmutableCollections {
...
static final class List0<E> extends AbstractImmutableList<E> {
...
}
static final class List1<E> extends AbstractImmutableList<E> {
...
}
static final class List2<E> extends AbstractImmutableList<E> {
...
}
static final class ListN<E> extends AbstractImmutableList<E> {
...
}
}
So this is not an ArrayList (neither a LinkedList). The only things you need to know is that it is immutable and satisfies the List
interface contract.
However, it is unclear about the specific type of the returned object.
And that is all you need to know! The whole point is: these methods do return some List<Whatever>
on purpose. The thing that you get back is guaranteed to fulfill the public contract denoted by the List interface. It is a list of the things given to that method, in the same order as those things were written down.
You absolutely should avoid writing any code that needs to know more about the lists returned by these methods! That is an implementation detail which should not matter to client code invoking these methods!
In that sense: your focus should be much more on the client side - for example by avoiding that raw type you are using in your example (using List
without a specific generic type).
Though the question seems to have been answered by @ZhekaKozlov and @GhostCat both in terms of what the return type would be(ImmutableCollections.List
) and how it has been created package private and is not a public API. Also adding to the facts that the implementation of these factory methods guarantees to fulfill the public contract denoted by the List interface.
To further provide a gist of the implementation of the ImmutableCollections
then Set, Map and List a step further in it. I would add a sample representation for a List
which is quite similar for Map
and Set
.
The ImmutableCollections
currently implements these factory methods on the interface List
using:
abstract static class AbstractImmutableList<E>
which extends the AbstractList
class and throws an UnsupportedOperationException
for all the possible operations overriding their implementation. Meaning no more operations allowed on the collection, making them equivalent to Java Immutable Collections.
Furthermore, this is extended by a class
static final class ListN<E> extends AbstractImmutableList<E>
with a constructor to evaluate certain checks for the input and its elements being NonNull to return the object consisting of an E[] elements
(array of elements of type E) and overrides certain implementations as .get(int idx)
, .contains(Object o)
based out of these elements.
The way it goes on for Map and Set is similar, just that the validations on top of the elements or a pair of key and value are ensured there. Such that you can't create these(throws IllegalArgumentException and NullPointer exceptions respectively) :
Set<String> set2 = Set.of("a", "b", "a");
Map<String,String> map = Map.of("key1","value1","key1","value1");
Set<String> set2 = Set.of("a", null);
Map<String,String> map = Map.of("key1",null);
Actually the same idea is in Collectors.toList
for example - you get a List
back and the documentation specifically says : There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned
. At the moment it is an ArrayList
returned, but obviously this can change at any point in time.
I wonder if the same should be done here - to explicitly mention that the type is a List
and nothing more. This let's a lot of ground for future implementations to decide what type to return that would fit best - speed, space, etc.
List.of
returns a List
of special type like Collections.UnmodifiableList
. It is neither an ArrayList
nor LinkedList
. It will throw an exception when you will try to modify it.