That line creates an empty list of strings by calling a static method with a generic type parameter.
Inside the Collections
class, there is a static method emptyList
declared like:
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
This has a generic type parameter T
. We call call this method by using:
List<String> list = Collections.emptyList();
and T
is infered to be a String
because of the type of list
.
We can also specify the type of T
by putting it in angle brackets when calling emptyList
. This may be needed if we want a more specific type than is inferred:
List<? extends Object> list = Collections.<String>emptyList();
emptyList<String>()
is not correct because that placement is only valid when creating
instances of generic classes, not calling methods. When using new
there are two possible
type parameters, the ones before the class name are for the constructor only, and the ones after the class name are for the whole instance, so with the class:
class MyClass<A> {
public <B> MyClass(A a, B b) {
System.out.println(a + ", " + b);
}
}
We can call its constructor where A
is String
and B
is Integer
like:
MyClass<String> a = new <Integer>MyClass<String>("a", 3);
or by using type inference:
MyClass<String> a = new MyClass<>("a", 3);
See also: