Ref

  • In the generic <? > and what is the difference between | Segmentfault
  • Talk about it – Wildcards T, E, K, V, JAVA generics? | the nuggets
  • Java generics important objective: don’t let the cat don’t stand on the dog team | Blog
  • Java generics: a generic class, generic interfaces and generic methods | Segmentfault
  • In Java generics? And distinguish T | Blog
  • Java generics <? Super T> super. What is the difference and extends | zhihu

Overview

Java Generics is a new feature introduced in JDK 5. Generics provide compile-time type-safety checks that allow developers to detect illegal types at compile time.

The nature of generics is parameterized typing, which means that the data type being operated on is specified as a parameter.

Wildcard T, E, K, V?

When we define generic classes, generic methods, and generic interfaces, we often encounter many different wildcards, such as T, E, K, V,? And so on. Essentially, these are wildcards, no difference, just code conventions.

  • ?Represents an indeterminate Java type
  • T(type) represents a specific Java type
  • K V(Key Value) represents key and value in Java key values
  • EOn behalf of the element (element)

The use of generics

Generics are used in three main ways

  1. A generic class
  2. A generic interface
  3. Generic method

A generic class

//lmy material-jsf
@Data
public class AssembleKeyInfo<T> {
    // long id set
    private Set<Long> longIds = Sets.newHashSet();
    // string id set
    private Set<String> strIds = Sets.newHashSet();
    // int id set
    private Set<Integer> intIds = Sets.newHashSet();

    private T keyData;
}
Copy the code
public class Container<K.V> {
    private K key;
    private V value;

    public Container(K k, V v) {
        key = k;
        value = v;
    }

    public K getKey(a) {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue(a) {
        return value;
    }

    public void setValue(V value) {
        this.value = value; }}Copy the code

A generic interface

// Interface definition
public interface Generator<T> {
    public T next(a);
}
Copy the code
// Implement the interface
public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple"."Banana"."Pear"};

    @Override
    public String next(a) {
        Random rand = new Random();
        return fruits[rand.nextInt(3)]; }}Copy the code
/ / call
public class Main {

    public static void main(String[] args) {
        FruitGenerator generator = newFruitGenerator(); System.out.println(generator.next()); System.out.println(generator.next()); System.out.println(generator.next()); System.out.println(generator.next()); }}Copy the code

Generic method

public class Main {

    public static <T> void out(T t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        out("findingsea");
        out(123);
        out(11.11);
        out(true); }}Copy the code

Type erasure

  • Java generics important objective: don’t let the cat don’t stand on the dog team | Blog

True and false generics

  • True generics: Types in generics are real.
  • Pseudo-generics: Type checking only at compile time, erasing type information at run time.

Java pseudo-generics

The concept of generics was introduced in Java version 1.5; before that, there was no concept of generics. But it is clear that generic code is very compatible with previous versions of code. This is because generics in Java are pseudo-generics, and the generics information only exists at compile time. Before entering the JVM, generic-related information is erased, a technical term called type erasure.

List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
		
System.out.println(l1.getClass() == l2.getClass()); //true 
Copy the code

List

and List

are both list. Class in the JVM, that is, the generic information is erased.

Impact of type erasure

Combine an example to understand the impact of type erasure.

public class Cmower {

	class Dog {}class Cat {}public static void main(String[] args) {
		Cmower cmower = new Cmower();
		Map<String, Cat> map = new HashMap<>();
		Map<String, Dog> map1 = new HashMap<>();
		
		// The method put(String, Cmower.Cat) in the type Map<String,Cmower.Cat> is not applicable for the arguments (String, Cmower.Dog)
		//map.put("dog",cmower.new Dog());
		
		System.out.println(map.getClass());
		// Output: class java.util.hashmap
		System.out.println(map1.getClass());
		// Output: class java.util.hashmap}}Copy the code

The map key is Cat, so it is not allowed to put a Dog. Otherwise The compiler will say The method put(String, Cat) in the type Map

is not applicable for the arguments (String, cmower.dog).
,>

But the problem is that map has a HashMap Class type, and Map1 has a HashMap Class type — that is, Java code runs without knowing that the map key is Cat and map1 key is Dog.

So, try something scary: since the run-time generic information is erased, and reflection determines the type information at run time, is it possible to put a Dog on a Map with key Cat using reflection?

Let’s give it a try.

public class Cmower {

	class Dog {}class Cat {}public static void main(String[] args) {
		Cmower cmower = new Cmower();
		Map<String, Cat> map = new HashMap<>();
		
		try {
			Method method = map.getClass().getDeclaredMethod("put",Object.class, Object.class);
			
			method.invoke(map,"dog", cmower.new Dog(a));
			
			System.out.println(map);
			// {dog=com.cmower.java_demo.sixteen.Cmower$Dog@55f96302}
		} catch(NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); }}}Copy the code

As you can see, we actually put a Dog on the Map with the key Cat!

Java’s designers are introduced in the JDK 1.5 generics, but for the sake of taking care of previous design flaws, compatible with the generic code at the same time, have to make a compromise strategy: compile-time strict in generic, but the runtime generic erased — to be compatible with previous versions, but also upgrade extend new functions, really not easy!

<? >and<T>

  • Talk about it – Wildcards T, E, K, V, JAVA generics? | the nuggets

“T” is declared when you define a class or method, “?” Is passed in when called, they are different concepts.

  • Class<T>At instantiation time,TYou want to replace it with a concrete class
  • Class<? >Is a wildmatch generic,?Can represent any type
  • <? extends T>Is an upper bound wildcard that accepts type E or a subtype of E
  • <? super E>Is a lower bound wildcard that accepts type E or a parent of type E
ArrayList<T> al = new ArrayList<T>(); // Specify that collection elements must be of type T onlyArrayList<? > al =newArrayList<? > ();Collection elements can be of any type

ArrayList<? extends E> al = new ArrayList<? extends E>();
Copy the code
  • Upper Bounds Wildcards:<? extends E>
  • Lower Bounds Wildcards:<? super E>