What is the difference between Collection<?> and Collection<T>

Solution 1:

Collection<?> is a collection of unknown type parameter.

As far as the caller is concerned, there is no difference between

void printCollection(Collection<?> c) { ... }

and

<T> void printCollection(Collection<T> c) { ... }

However, the latter allows the implementation to refer to the collection's type parameter and is therefore often preferred.

The former syntax exists because it is not always possible to introduce a type parameter at the proper scope. For instance, consider:

List<Set<?>> sets = new ArrayList<>();
sets.add(new HashSet<String>());
sets.add(new HashSet<Integer>());

If I were to replace ? by some type parameter T, all sets in sets would be restricted to the same component type, i.e. I can no longer put sets having different element types into the same list, as evidenced by the following attempt:

class C<T extends String> {
    List<Set<T>> sets = new ArrayList<>();

    public C() {
        sets.add(new HashSet<String>()); // does not compile
        sets.add(new HashSet<Integer>()); // does not compile
    }
}

Solution 2:

The declaration Collection<?> (pronounced "collection of unknown") is a collection whose element type matches anything, whereas Collection<T> stands for a collection of type T.

As usual Angelika Langer's FAQ on generics has an extensive discussion on the topic, a must-read for fully understanding all about generics in Java, and unbounded wildcards (the subject of this question) in particular. Quoting from the FAQ:

The unbounded wildcard looks like " ? " and stands for the family of all types. The unbounded wildcard is used as argument for instantiations of generic types. The unbounded wildcard is useful in situations where no knowledge about the type argument of a parameterized type is needed

For further technical details, check out the section §4.5.1 Type Arguments and Wildcards of the Java Language Specification, which states that:

Type arguments may be either reference types or wildcards. Wildcards are useful in situations where only partial knowledge about the type parameter is required.