T, E, K, V in generics, remember?

  • preface

  • Benefits of generics

  • Wildcards in generics

    • Commonly used T, E, K, V,?

    • ? Unbounded wildcards

    • Upper bound wildcard <? extends E>

    • Wildcard lower bound? super E>

    • ? Difference between and T

  • Class < T > and "class <? > difference

  • Summary


Java generics is a new feature introduced in JDK 5. Generics provides a compile time type safety detection mechanism, which allows developers to detect illegal types at compile time.

The essence of generics is parameterized type, that is, the data type operated on is specified as a parameter.

Benefits of generics

In the absence of generics, the "arbitrary" of parameters can be realized by referring to the type Object. The disadvantage of "arbitrary" is to make explicit forced type conversion, which requires developers to predict the actual parameter types. For the case of cast error, the compiler may not prompt the error, and the exception occurs only when running, which is itself a security risk.

The advantage of generics is that it can check type safety at compile time, and all casts are automatic and implicit.

public class GlmapperGeneric<T> {
  private T t;
    public void set(T t) { this.t = t; }
    public T get() { return t; }

    public static void main(String[] args) {
        // do nothing

    * Do not specify type
  public void noSpecifyType(){
    GlmapperGeneric glmapperGeneric = new GlmapperGeneric();
    //Cast required
    String test = (String) glmapperGeneric.get();

    * Specify type
  public void specifyType(){
    GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric();
    //Cast is not required
    String test = glmapperGeneric.get();

The specififytype method in the above code omits the mandatory conversion. It can check the type safety during compilation and can be used on classes, methods and interfaces.

Wildcards in generics

When defining generic classes, generic methods and generic interfaces, we often encounter many different wildcards, such as T, E, K, V and so on. What do these wildcards mean?

Commonly used T, E, K, V,?

In essence, these are wildcards, no difference, but a conventional thing in coding. For example, we can replace t in the above code with any letter between a and Z, which will not affect the normal operation of the program, but if we replace T with other letters, it may be less readable. Usually, t, E, K, V,? It is agreed as follows:

  • ? Represents an ambiguous java type

  • T (type) represents a specific java type

  • K V (key value) respectively represents the Key Value in the java Key Value

  • E (element) stands for Element

? Unbounded wildcards

Let's start with a small example. The original text is here.

I have a parent Animal and several subclasses, such as dogs and cats. Now I need a list of animals. My first idea is like this:

List<Animal> listAnimals

But the boss does think so:

List<? extends Animal> listAnimals

Why use wildcards instead of simple generics? Wildcards are meaningless when declaring local variables, but they are very important when you declare a parameter for a method.

static int countLegs (List<? extends Animal > animals ) {
    int retVal = 0;
    for ( Animal animal : animals )
        retVal += animal.countLegs();
    return retVal;

static int countLegs1 (List< Animal > animals ){
    int retVal = 0;
    for ( Animal animal : animals )
        retVal += animal.countLegs();
    return retVal;

public static void main(String[] args) {
    List<Dog> dogs = new ArrayList<>();
  //No error will be reported
    countLegs( dogs );
 //Error reporting

When countLegs1 is called, it will be red, and the error message is as follows:

Therefore, for types that are uncertain or do not care about the actual operation, you can use infinite wildcards (a question mark in angle brackets, i.e. <? >), indicating that you can hold any type. For example, the countLegs method defines the previous session, but does not care about the specific type. Therefore, all subclasses of the incoming Animal can be supported without error. Not countLegs1.

Upper bound wildcard <? extends E>

Previous: declared with the extends keyword, indicating that the parameterized type may be the specified type or a subclass of this type.

Using extensions in type parameters means that the parameters in this generic type must be e or a subclass of E, which has two advantages:

  • If the type passed in is not e or a subclass of E, the compilation will not succeed

  • You can use the method of E in generics, otherwise you have to convert to e to use it

private <K extends A, E extends B> E test(K arg1, E arg2){
    E result = arg2;
    return result;

If there are multiple upper limits of type parameters in the type parameter list, separate them with commas

Lower bound wildcard <? super E>

Lower bound: declared with super, indicating that the parameterized type may be the specified type or the parent type of this type, up to Object

Using super in type parameters means that the parameters in this generic type must be e or the parent class of E.

private <T> void test(List<? super T> dst, List<T> src){
    for (T t : src) {

public static void main(String[] args) {
    List<Dog> dogs = new ArrayList<>();
    List<Animal> animals = new ArrayList<>();
    new Test3().test(animals,dogs);
//Dog , is a subclass of , Animal ,
class Dog extends Animal {


dst type "greater than or equal to" src type. Here "greater than or equal to" means that the range represented by dst is larger than src, so the container that can hold dst can also hold src.

? Difference between and T

? And t both represent uncertain types. The difference is that we can operate on T, but for? No, for example:

T t = operate();

?car = operate();

To summarize briefly:

T is a definite type, which is usually used for the definition of generic classes and generic methods,? Is an uncertain type, which is usually used for the calling code and formal parameters of generic methods. It cannot be used to define classes and generic methods.

Difference 1: ensure the consistency of generic parameters through T

//Ensure the consistency of  generic parameters through  T 
public <T extends Number> void
test(List<T> dest, List<T> src)

//The wildcard character , is uncertain, so this method cannot guarantee that two , lists , have the same element type
public void
test(List<? extends Number> dest, List<? extends Number> src)

As in the following code, the agreed T is a subclass of Number, but the declaration uses String, so an error will be reported in red.

There is no guarantee that two lists have the same element type

GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric<>();
List<String> dest = new ArrayList<>();
List<Number> src = new ArrayList<>();

The above code will not report an error in the compiler, but when entering the internal operation of testNon method (such as assignment), type conversion is still required for dest and src.

Difference 2: type parameters can be multi qualified, but wildcards cannot

Use the & symbol to set multi boundaries and specify that the generic type t must be a common subtype of MultiLimitInterfaceA and MultiLimitInterfaceB. At this time, the variable t has all the qualified methods and properties. For wildcards, because it is not a definite type, multiple qualifications cannot be made.

Difference 3: wildcards can use super class qualification, but type parameters cannot

Type parameter T has only one type qualification method:

T extends A

But wildcards? There are two restrictions:

? extends A
? super A

Difference between Class and Class

Previously introduced? And T, so for class < T > and < class <? > What's the difference? Class < T > and "class <? >

The most common is the use in the reflection scene. Here we will explain it with a piece of emitted code.

//Generate multi limit by reflection
//Object. What is obvious here is that we need to use cast
MultiLimit multiLimit = (MultiLimit)

For the above code, if the type of reflection is not MultiLimit class during the run time, it will report Java Lang.classcastexception error.

In this case, the following code can be used instead, so that the type problem can be directly checked at compile time:

Class < T > when instantiating, t should be replaced with a specific class. Class<?> It's a wildcard generic,? It can represent any type, so it is mainly used for restrictions when declaring. For example, we can state:

public Class<?> clazz;
//No, because T # needs to specify the type
public Class<T> clazzT;

So when you don't know what type of Class to declare, you can define a Class <? >.

If you also want to create public class < T > clazzt; In this case, the current class must also specify t,

public class Test3<T> {
    public Class<?> clazz;
    //No error will be reported
    public Class<T> clazzT;


This paper sorts out some points in JAVA generics, which are not very complete, for reference only. If there is anything wrong in the text, please correct it.

Tags: Java programming language

Posted by jb60606 on Mon, 23 May 2022 23:59:38 +0300