328

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?

0

6 Answers 6

292

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:

6
  • 2
    It looks like the link to the PDF is broken. I've found what appears to be a copy here, but I can't be 100% certain since I don't know what the original looked like.
    – John
    Commented May 30, 2017 at 16:54
  • 2
    @John: Yup, that's the one. Will edit a link in, whether that one or an Oracle one...
    – Jon Skeet
    Commented May 30, 2017 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
    Commented Dec 24, 2018 at 12:08
  • 3
    @sofs1: There's nothing special about T and E - they're just identifiers. You could write KeyValuePair<K, V> for example. ? has special meaning though.
    – Jon Skeet
    Commented Dec 24, 2018 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<hello_world> is valid. Using a single upper-case letter is a naming standard, which is recommended in the Java Language Specification: "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
    Commented Aug 31, 2020 at 12:33
262

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

4
  • 32
    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
    Commented Nov 9, 2015 at 14:55
  • A more detailed and clear description is available in this article oracle.com/technetwork/articles/java/…
    – fgul
    Commented Jan 13, 2019 at 8:12
  • 13
    You didn't explain to the question mark. Downvoted.
    – shinzou
    Commented May 7, 2019 at 16:05
  • 1
    Why is this even answer, anyway?
    – Farid
    Commented Oct 7, 2021 at 9:04
189

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.

10
  • "public void foo(List<? extends Number> numbers) {...}" should "extends" be "super" ?
    – 1a1a11a
    Commented Jun 6, 2015 at 6: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<Integer>, List<Float>, 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. Commented Jun 21, 2015 at 23:37
  • 5
    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 ! Commented Apr 17, 2017 at 23:45
  • 2
    This is the only answer that actually answers the question Commented Dec 13, 2021 at 9:48
  • 1
    @HawkeyeParker Thank you for explanation, well detailed! Commented Dec 23, 2022 at 7: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
0
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

0
5

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())
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.