What is the difference between 'E', 'T', and '?' for Java generics?

JavaGenerics

Java Problem Overview


I come across Java code like this:

public interface Foo<E> {}

public interface Bar<T> {}

public interface Zar<?> {}

What is the difference among all three of the above and what do they call this type of class or interface declarations in Java?

Java Solutions


Solution 1 - Java

Well there's no difference between the first two - they're just using different names for the type parameter (E or T).

The third isn't a valid declaration - ? is used as a wildcard which is used when providing a type argument, e.g. List<?> foo = ... means that foo refers to a list of some type, but we don't know what.

All of this is generics, which is a pretty huge topic. You may wish to learn about it through the following resources, although there are more available of course:

Solution 2 - Java

It's more convention than anything else.

  • T is meant to be a Type
  • E is meant to be an Element (List<E>: a list of Elements)
  • K is Key (in a Map<K,V>)
  • V is Value (as a return value or mapped value)

They are fully interchangeable (conflicts in the same declaration notwithstanding).

Solution 3 - Java

The previous answers explain type parameters (T, E, etc.), but don't explain the wildcard, "?", or the differences between them, so I'll address that.

First, just to be clear: the wildcard and type parameters are not the same. Where type parameters define a sort of variable (e.g., T) that represents the type for a scope, the wildcard does not: the wildcard just defines a set of allowable types that you can use for a generic type. Without any bounding (extends or super), the wildcard means "use any type here".

The wildcard always come between angle brackets, and it only has meaning in the context of a generic type:

public void foo(List<?> listOfAnyType) {...}  // pass a List of any type

never

public <?> ? bar(? someType) {...}  // error. Must use type params here

or

public class MyGeneric ? {      // error
    public ? getFoo() { ... }   // error
    ...
}

It gets more confusing where they overlap. For example:

List<T> fooList;  // A list which will be of type T, when T is chosen.
                  // Requires T was defined above in this scope
List<?> barList;  // A list of some type, decided elsewhere. You can do
                  // this anywhere, no T required.

There's a lot of overlap in what's possible with method definitions. The following are, functionally, identical:

public <T> void foo(List<T> listOfT) {...}
public void bar(List<?> listOfSomething)  {...}

So, if there's overlap, why use one or the other? Sometimes, it's honestly just style: some people say that if you don't need a type param, you should use a wildcard just to make the code simpler/more readable. One main difference I explained above: type params define a type variable (e.g., T) which you can use elsewhere in the scope; the wildcard doesn't. Otherwise, there are two big differences between type params and the wildcard:

Type params can have multiple bounding classes; the wildcard cannot:

public class Foo <T extends Comparable<T> & Cloneable> {...}

The wildcard can have lower bounds; type params cannot:

public void bar(List<? super Integer> list) {...}

In the above the List<? super Integer> defines Integer as a lower bound on the wildcard, meaning that the List type must be Integer or a super-type of Integer. Generic type bounding is beyond what I want to cover in detail. In short, it allows you to define which types a generic type can be. This makes it possible to treat generics polymorphically. E.g. with:

public void foo(List<? extends Number> numbers) {...}

You can pass a List<Integer>, List<Float>, List<Byte>, etc. for numbers. Without type bounding, this won't work -- that's just how generics are.

Finally, here's a method definition which uses the wildcard to do something that I don't think you can do any other way:

public static <T extends Number> void adder(T elem, List<? super Number> numberSuper) {
    numberSuper.add(elem);
}

numberSuper can be a List of Number or any supertype of Number (e.g., List<Object>), and elem must be Number or any subtype. With all the bounding, the compiler can be certain that the .add() is typesafe.

Solution 4 - Java

A type variable, <T>, can be any non-primitive type you specify: any class type, any interface type, any array type, or even another type variable.

The most commonly used type parameter names are:

  • E - Element (used extensively by the Java Collections Framework)
  • K - Key
  • N - Number
  • T - Type
  • V - Value

In Java 7 it is permitted to instantiate like this:

Foo<String, Integer> foo = new Foo<>(); // Java 7
Foo<String, Integer> foo = new Foo<String, Integer>(); // Java 6

Solution 5 - Java

The most commonly used type parameter names are:

E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types

You'll see these names used throughout the Java SE API

Solution 6 - Java

compiler will make a capture for each wildcard (e.g., question mark in List) when it makes up a function like:

foo(List<?> list) {
    list.put(list.get()) // ERROR: capture and Object are not identical type.
}

However a generic type like V would be ok and making it a generic method:

<V>void foo(List<V> list) {
    list.put(list.get())
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaceView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - Javaratchet freakView Answer on Stackoverflow
Solution 3 - JavaHawkeye ParkerView Answer on Stackoverflow
Solution 4 - JavaUvaView Answer on Stackoverflow
Solution 5 - JavaWaqas AhmedView Answer on Stackoverflow
Solution 6 - JavaTiinaView Answer on Stackoverflow