325

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?

Isaac Moore
  • 240
  • 1
  • 2
  • 15
ace
  • 11,526
  • 39
  • 113
  • 193

6 Answers6

288

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:

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    It looks like the link to the PDF is broken. I've found what appears to be a copy [here](https://www.cs.rice.edu/~cork/312/Readings/GenericsTutorial.pdf), but I can't be 100% certain since I don't know what the original looked like. – John May 30 '17 at 16:54
  • 2
    @John: Yup, that's the one. Will edit a link in, whether that one or an Oracle one... – Jon Skeet May 30 '17 at 17:03
  • Is there anything other than T, E and ? used in generics? If so what are they and what does they mean? – sofs1 Dec 24 '18 at 12:08
  • 3
    @sofs1: There's nothing special about `T` and `E` - they're just identifiers. You could write `KeyValuePair` for example. `?` has special meaning though. – Jon Skeet Dec 24 '18 at 12:12
  • 2
    @JonSkeet *"they're just identifiers"*, which means they must follow the same name constraints as class names, field names, method names, etc. E.g. `Foo` is valid. Using a single upper-case letter is a naming standard, which is recommended in the [Java Language Specification](https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.1): *"Type variable names should be pithy (single character if possible) yet evocative, and should not include lower case letters. This makes it easy to distinguish type parameters from ordinary classes and interfaces."* – Andreas Aug 31 '20 at 12:33
254

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

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • 30
    The letter between the < > is just a name. What you describe in your answer are just conventions. It doesn't even have to be a single, upper-case letter; you can use any name that you like, just like you can give classes, variables etc. any name you like. – Jesper Nov 09 '15 at 14:55
  • A more detailed and clear description is available in this article https://www.oracle.com/technetwork/articles/java/juneau-generics-2255374.html – fgul Jan 13 '19 at 08:12
  • 13
    You didn't explain to the question mark. Downvoted. – shinzou May 07 '19 at 16:05
  • 1
    Why is this even answer, anyway? – Farid Oct 07 '21 at 09:04
183

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.

Hawkeye Parker
  • 7,817
  • 7
  • 44
  • 47
  • "public void foo(List extends Number> numbers) {...}" should "extends" be "super" ? – 1a1a11a Jun 06 '15 at 06:44
  • 1
    No. The point of that example is to show a signature which polymorphically supports a List of Number and the sub-types of Number. For this, you use "extends". I.e., "pass me a List of Number _or_ anything that extends Number" (List, List, whatever). A method like this might then iterate through the list and, for each element, "e", execute, e.g., e.floatValue(). Doesn't matter what sub-type (extension) of Number you pass -- you'll always be able to ".floatValue()", because .floatValue() is a method of Number. – Hawkeye Parker Jun 21 '15 at 23:37
  • On your last example, "List super Number>" could simply be "List" since the method does not allow anything more generic. – jessarah Jul 12 '16 at 10:05
  • @jessarah nope. Maybe my example is unclear, but I mention in the example that adder() could take a List (Object is a superclass of Number). If you want it to be able to do this, it must have the signature "List super Number>". That's exactly the point of "super" here. – Hawkeye Parker Aug 05 '16 at 01:11
  • 4
    This answer is very very good in explaining the differences between wildcards and type parameters, there should be one dedicated question with this answer. I am going more deep in generics lately and this answer helped me a lot in putting things together, many precise infos in short, thanks ! – Testo Testini Apr 17 '17 at 23:45
  • Very nice answer last example should be more clear. Thanks for such a well organized answer – Pawan Kumar Jul 28 '18 at 06:36
  • From docs.oracle: _"The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific)"_ In reaction to: _"you should use a wildcard just to make the code simpler/more readable"_ – vaultboy Jun 21 '19 at 13:59
  • Good answer, pal – max Mar 15 '21 at 16:20
  • 1
    This is the only answer that actually answers the question – chill appreciator Dec 13 '21 at 09:48
  • 1
    @HawkeyeParker Thank you for explanation, well detailed! – Moaaz Gaballah Dec 23 '22 at 07:09
31

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Uva
  • 752
  • 1
  • 6
  • 10
10

The most commonly used type parameter names are:

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

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

daniu
  • 14,137
  • 4
  • 32
  • 53
Waqas Ahmed
  • 1,780
  • 1
  • 14
  • 15
4

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())
}
Tiina
  • 4,285
  • 7
  • 44
  • 73