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

ID : 10273

viewed : 12

Tags : javagenericsjava

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

vote vote

96

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:

vote vote

80

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).

vote vote

77

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.

vote vote

68

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 
vote vote

56

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

Top 3 video Explaining What is the difference between 'E', 'T', and '?' for Java generics?

Related QUESTION?