71

I just studied about generic programming, the List<E> interface, and ArrayList, so I can understand the statement below.

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

But I don't understand the next statement which I saw while surfing the web.

List<String> list2 = Collections.<String>emptyList();
  1. What is Collections? Why isn't it Collections<E> or Collections<String>?
  2. Why is <String> placed before the method name emptyList?

(Isn't emptyList<String>() correct for Generic?)

  1. What does the statement mean?
Chris Hayes
  • 11,471
  • 4
  • 32
  • 47
Jenix
  • 2,996
  • 2
  • 29
  • 58
  • [`Collections`](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html) is a Java class. – PM 77-1 Dec 29 '14 at 05:20
  • The `Collection` is the interface and `collections` is a static class which contains all methods – Ameya Deshpande Dec 29 '14 at 05:21
  • 40
    **This is a perfectly valid question**. Not sure it was treated so harshly. To someone who doesn't understand static method generics, it could be a confusing statement. Voting to re-open. – Qix - MONICA WAS MISTREATED Dec 29 '14 at 05:22
  • 3
    Also voted to reopen. The _title_ of the question is too broad, probably, but the actual question in the body is pretty specific. Perhaps editing the title is better than closing. – TM. Dec 29 '14 at 05:32
  • 3
    Seems to me that the number of concepts that need to be explained to answer this question is so high that an answer would almost constitute an intro Java tutorial. But [here's my explanation of generic methods](http://stackoverflow.com/a/21298123/402884). As for question 2, read about static imports. – Chris Martin Dec 29 '14 at 05:34
  • @ChrisMartin I think it is pretty borderline. I feel like the question was direct enough to reopen though. – Dev Dec 29 '14 at 05:38
  • 2
    @ChrisMartin See given answers. They seem to do a pretty good job. OP understands generics, but *method* generics is an (understandably) new concept that aren't as common in the wild. – Qix - MONICA WAS MISTREATED Dec 29 '14 at 05:55
  • Check this [link](https://weblogs.java.net/blog/carcassi/archive/2010/04/09/two-problems-generics-java-0) – Hana Bzh Dec 29 '14 at 05:55

5 Answers5

57

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:

fgb
  • 18,439
  • 2
  • 38
  • 52
  • 4
    Might want to mention `Collections` is one of those classes that is there *only* to provide static methods; it's not intended to be instantiated itself (and can't be, in turn). – Qix - MONICA WAS MISTREATED Dec 29 '14 at 05:56
  • I'm no Java expert but it seems to me, then, that `foo()` is _not_ "calling a constructor" at all, even though the resulting object construction results in an invocation of `foo`'s constructor (among all the other steps taken to instantiate a `foo`). Then there is no actual inconsistency or discrepancy against the generic method call syntax `bar()` (which, coming from a C++ background, is mighty weird let me just say!). – Lightness Races in Orbit Dec 29 '14 at 16:58
  • 9
    I checked the constructor syntax, and it turns out that constructors can have their own type parameters too, so we can have syntax containing two type parameter expressions like `new MyClass(2)`. – fgb Dec 29 '14 at 17:38
  • @fgb Huh... that's new. I guess I've never seen something like that in the wild. Interesting! – Qix - MONICA WAS MISTREATED Dec 30 '14 at 13:55
  • "emptyList() is not correct because that placement is only valid when calling constructors, not static methods" This statement is confusing; since this question is about generic methods, it sounds like you are talking about generic constructors. But you are not. `SomeClass()` is for creating an instance of a generic class with a non-generic constructor. To create an instance of a class using a generic constructor, you would do something like `new SomeClass()`. – newacct Dec 31 '14 at 10:55
11

What is Collections? Why isn't it Collections<E> or Collections<String>?

Collections is a JDK class.

This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

It's not generic and cannot be instantiated.

Why is <String> placed before the method name emptyList?

Collections#emptyList is a generic method. Here, we are explicitly specifying a type argument, String.

(Isn't emptyList<String>() correct for Generic?)

No, in Java, generic type arguments for methods come before the method name.

What does the statement mean?

We are invoking the static emptyList method and assigning its return value to a variable of type List<String>.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
9

In a nutshell, this creates an empty, immutable list of strings.

Let's look at the expression bit by bit.

Collections is the name of a class. From the Javadoc:

This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends.

emptyList() is the name of a static method defined in the Collections class (Javadoc). It is a generic method, and the <String> in Collections.<String>emptyList() specifies the generic type argument.

The method returns a List<T>, which in this case is List<String>: a list of strings. More specifically, it returns an empty, immutable list of strings.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • `+1` for highlighting (although present in the docs) *immutability* of the returned collection. –  Dec 29 '14 at 21:36
6

1.Collection is an interface and collections is a static class consists exclusively of static methods that operate on or return collections. Hence we cannot use Collections<E> or Collections<String>.

2.<String> before emptyList(used to get the empty list that is immutable) denotes that only String values can be added to it. Like:

list2.add("A");
list2.add("B");

3.The statement means that it will create a immutable empty list of type List.

You can check out this link: Difference between Java Collection and Collections

Community
  • 1
  • 1
Leo
  • 5,017
  • 6
  • 32
  • 55
  • 2
    `denotes that only String values can be added to it.` A more precise description is that: it declares the parameter type of the method to be String, so that the return value is a homogeneous List of String. – nhahtdh Dec 30 '14 at 03:43
6

Firstly, Collections is a helper library of static methods that operate on various types of collections. If you've done any sort of C++ programming, it's very synonymous to the <algorithm> library of functions.

In this case, you're invoking the static method emptyList(), which returns an empty list of a particular type. Since these methods still require a type, but Collections' methods can refer to many types, you have to specify the type upon invocation.

In order to call a generic method, you must call it with the parameter list (i.e. <String>) before the method name, but after the dot.

List<String> someList = Collections.<String>emptyList();
Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145