JAVA generic wildcards T, E, K, V differences, t and Class < t >, Class <? > Differences between

Posted by santhosh_89 on Fri, 04 Feb 2022 13:51:28 +0100

https://www.jianshu.com/p/95f349258afb

1. First explain the concept of generics

Generics are Java SE
The new feature of 1.5, the essence of generics is parameterized type, that is, the data type operated is specified as a parameter. This parameter type can be used in the creation of classes, interfaces and methods, which are called generic classes, generic interfaces and generic methods respectively. The advantage of introducing generics into Java language is safety and simplicity.
In Java SE
Before 1.5, when there is no generic type, the "arbitrary" of parameters is realized by referencing the type Object. The disadvantage of "arbitrary" is to do 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 a security risk.
The advantage of generics is that type safety is checked at compile time, and all casts are automatic and implicit to improve the reuse rate of code.

The above content is extracted from Baidu Encyclopedia

Take chestnuts for example:
The Box class is defined as a generic class

public class Box<T> {
    private T object;

    public void set(T object) { this.object = object; }
    public T get() { return object; }
}

Create a Box object without generic parameters. It needs to be cast when finding the object

Box box2 = new Box();
box2.set(new Apple());
Apple apple = (Apple) box2.get();
Create a Box object with generic parameters, and there is no need to cast when obtaining the object

Box<Apple> box = new Box<Apple>();
box.set(new Apple());
Apple apple = box.get();

To sum up, the benefits of generics are
The forced conversion is omitted, and the type safety can be checked during compilation. It can be used in classes, methods and interfaces

However, when we define generic classes, generic methods and generic interfaces, we often encounter many different wildcards T, E, K, V and so on. What do these wildcards mean? Keep looking down

2. Let's talk about the difference between generic wildcards T, E, K and V

These are all wildcards belonging to java generics. At the beginning, I was dizzy when I saw so many wildcards. In fact, these are no different, but an agreed code, that is to say

Using the capital letters A,B,C,D... X,Y,Z is defined as generics. It is the same to replace T with A. here t is just the meaning of the name

  • ? 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

Take chestnuts for example:

public class Test<T> {    
  public List<T> list = new ArrayList<T>();   
  public static void main(String[] args) {
        Test<String> test = new Test<String>();
        test.list.add("hello");
        System.out.println(test.list);
    }}

and

public class Test<A> {    
  public List<A> list = new ArrayList<A>();   
  public static void main(String[] args) {
        Test<String> test = new Test<String>();
        test.list.add("hello");
        System.out.println(test.list);
    }}

Replacing T with A makes no difference in the execution effect, but we have agreed that t stands for type, so it's better to follow the agreed specifications to increase the readability of the code.

If you want to define multiple generic parameters, for example, two generic parameters
A typical chestnut is the key and value generics of Map. We can also define one of these generics

public interface Mymap<K, V> {
    public K getKey();
    public V getValue();
}

public class MymapImpl<K, V> implements Mymap<K, V> {

    private K key;
    private V value;

    public MymapImpl(K key, V value) {
    this.key = key;
    this.value = value;
    }

    public K getKey()   { return key; }
    public V getValue() { return value; }
}

Next, you can pass in any type and create an instance without converting the type

Mymap<String, Integer> mp1= new MymapImpl<String, Integer>("Even", 8);
Mymap<String, String>  mp2= new MymapImpl<String, String>("hello", "world");
Mymap<Integer, Integer> mp3= new MymapImpl<Integer, Integer>(888, 888);

If you want to define more than two, three or more generic parameters, you can use T1, T2,..., Tn, like this

public class Test<T1,T2,T3> {
   public void print(T1 t1,T2 t2,T3 t3){
        System.out.println(t1.getClass());
        System.out.println(t2.getClass());
        System.out.println(t3.getClass());
    }
}

3. Next, let's talk about List, List, List <? > difference

ArrayList al=new ArrayList(); The specified collection element can only be of type T

ArrayList<?> al=new ArrayList<?> (); Collection elements can be of any type, which is meaningless. It is generally in methods, just to illustrate usage

ArrayList<? extends E> al=new ArrayList<? extends E>();
Generic qualification:
? Extensions e: receive type E or subtype of E.
? super E: receive type E or parent type of e

  • The difference between Object and T is that Object is a real class and does not refer to anyone in general, while T can refer to Object in general, such as public void
    List can be passed in the printlist (list) {} method
    list type parameters can also be passed in, but public void
    Printlist (List) {} can only be passed in List
    list type parameter, because the Object type does not generally refer to who, but a certain type
  • ? What's the difference between and t? Is an uncertain class,? Both and t represent uncertain types, but if it is t, t can be operated in the function, such as T car=
    Getcar() instead of? car = getCar().

Let's compare these three kinds of chestnuts:

package com.lyang.demo.fanxing;

import java.util.Arrays;
import java.util.List;

/**
 * Test the difference between generic parameter Object and T
 * Created by yanglu on 2017/04/20.
 */
public class TestDifferenceBetweenObjectAndT {
    public static void printList1(List<Object> list) {
        for (Object elem : list)
            System.out.println(elem + " ");
        System.out.println();
    }

    public static <T> void printList2(List<T> list) {
        for (T elem : list)
            System.out.println(elem + " ");
        System.out.println();
    }

    public static  void printList3(List<?> list) {
        for (int i = 0;i<list.size();i++)
            System.out.println(list.get(i) + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        List<Integer> test1 = Arrays.asList(1, 2, 3);
        List<String>  test2 = Arrays.asList("one", "two", "three");
        List<Object> test3 = Arrays.asList(1, "two", 1.23);
        List<Fruit> test4 = Arrays.asList(new Apple(), new Banana());
        /*
        * The following sentence will compile and report an error because the parameters cannot be converted successfully
        * */
        printList1(test4);
        /**/
        printList1(test3);
        printList1(test3);
        printList2(test1);
        printList2(test2);
        printList2(test3);
        printList3(test1);
        printList3(test2);
        printList3(test3);
    }
}

4. Finally, T, Class, Class <? > difference

T is a specific class, such as String,List,Map... And so on. These belong to specific classes, which is easy to understand
**What is class? Class is also a class, but class is a class * * that stores the above String,List,Map... Class information. It's a little abstract. Let's look at it step by step.

There are three ways to get a Class:
1. Call the getClass() method of the Object Class to get the Class Object, which is also the most common method to generate the Class Object.
For example:

List list = null;
Class clazz = list.getClass();

2. Use the static forName() method in Class class to obtain the Class object corresponding to the string.

For example:

Class clazz = Class.forName("com.lyang.demo.fanxing.People");

3. The third method to get Class objects is very simple. If T is a Java type, then T.class represents the matching Class object.

Class clazz = List.class;

So here comes the question...? Class is created, but class and class <? > When does it apply??
Use Class and Class <? > Most of them occur in reflection scenarios. Let's first see what it is like to create a Class by reflection if we don't use generics.

People people = (People) Class.forName("com.lyang.demo.fanxing.People").newInstance();

See? Strong rotation is required. If the type of reflection is not the People class, it will be reported
java.lang.ClassCastException error.

After using Class generics, there is no need to force conversion

public class Test {
    public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        return clazz.newInstance();
    }

    public static void main(String[] args)  throws IllegalAccessException, InstantiationException  {
            Fruit fruit= createInstance(Fruit .class);
            People people= createInstance(People.class);
    }
}

What about Class and Class <? > What's the difference?
When Class is instantiated, T should be replaced with a concrete Class
Class<?> It's a wildcard generic,? It can represent any type and is mainly used for restrictions when declaring
For example, you can declare a

public Class<?> clazz;

But you can't declare one

public Class<T> clazz;

Because T needs to specify the type
Therefore, when you don't know what type of class to declare, you can define a class <? >, Class<?> It can be used for parameter type definition, method return value definition, etc.

I have submitted the code of all the above examples to GitHub. Interested students can go and have a look https://github.com/qwertyanglu/FanxingDemo

Topics: Java Back-end