javagenericscollectionstypesunbounded-wildcard

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


I am mainly a C# developer and I was teaching Data Structures to my friend and they use Java in their University and I saw such an expression in Java:

void printCollection(Collection<?> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

I haven't seen such a thing in C# so I wonder what's the difference between Collection<T> and Collection<?> in Java?

void printCollection(Collection<T> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

I think it could have been written in the way above too. The guy in the documentation was comparing Collection<Object> and Collection<T> though.

Examples are taken from http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html


Solution

  • 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
        }
    }