preface

Java Generics is a new feature introduced in JDK5. 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.

Benefits of generics

In the absence of generics, arguments can be “arbitrary” by referring to the type Object. The disadvantage of “arbitrary” is that explicit casts are required, which require the developer to advance the actual parameter types. In the case of a cast error, the compiler may not give an error until runtime, which in itself is a security risk.

The advantage of generics is that type safety can be checked 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} // Public void noSpecifyType(){GlmapperGeneric glmapperGeneric=new GlmapperGeneric(); glmapperGeneric.set("test"); // Cast String test=(String) glmappergeneric.get (); // specify SpecifyType public void SpecifyType(){GlmapperGeneric<String> GlmapperGeneric =new GlmapperGeneric(); glmapperGeneric.set("test"); String test= glmappergeneric.get ();Copy the code

SpecifyType methods in this code omit cast casting to check type safety at compile time and can be used on classes, methods, and interfaces.

Wildcards in generics

When we define generic classes, generic methods, and generic interfaces, we often encounter many different wildcards, such as T,E,K,V,? Wait, what do these wildcards mean?

The commonly used T, E, K, V,?

These are all wildcards, essentially, no difference, just conventions of coding. For example, we can replace the T in the above code with any letter between A and Z without affecting the normal operation of the program, but if we replace T with other letters, the readability may be weaker. In general, T,E,K,V, right? Here’s the deal:

  • ? Represents an indeterminate Java type
  • T(type) indicates a specific Java type
  • K and V are key values in Java key values
  • E (element) on behalf of the element

? I have a parent Animal and several subclasses, such as dog and cat. Now I need a list of animals. My first thought is this:

List<Animal> listAnimals;
Copy the code

But the boss thought something like this:

List<? extends Animal> listAnimalsCopy the code

Why use wildcards instead of simple generics? Wildcards don’t mean much when you declare local variables, but they are important when you declare a parameter to a method.

The upper bound wildcard
upper bound: Declared with the extends keyword to indicate that the parameterized type may be the specified type or a subclass of that type.

Using extends in a type parameter means that the parameter in the generic must be E or a subclass of E. This has two benefits:

  • If the type passed is not E or a subclass of E, the compilation fails
  • The E method can be used in generics, otherwise you need to strongly cast to E to use it
private <K extends A,E extends B> E test(K arg1, E arg2){ E result=arg2; arg2.compareTo(arg1); // indicates that E's method can be used without casting //.... return result;Copy the code

If there are more than one upper limit of type parameters in the type parameter list, separate them with commas.

The lower wildcard
lower bound: declared with super to indicate that the parameterized type may be the specified type or a parent of the type, up to Object

? And T

List<T> List =new ArrayList<T>(); // The elements in the collection can be of any type. > list=new ArrayList<? > ();Copy the code

? And T are indeterminate types, the difference is that we can operate on T, but right? No, like this:

T =operate(); // No? car=operate();Copy the code

A simple summary is as follows:

T is a definite type, usually used in the definition of generic classes and generic methods,? Is an indeterminate type that is usually used for calling code and parameters of generic methods and cannot be used to define classes and generic methods

Difference 1: T is used to ensure consistency of generic parameters

Public <T extends Number> void test(List<T> dest,List<T> SRC) Public void test(List<? extends Number> dest,List<? extends Number> src)Copy the code

As in the following code, the convention T is a subclass of Number, but the declaration is a String, so it will float red error, this is found at compile time.

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

Copy the code

The above code does not guarantee that two lists will have the same element type and the compiler will not report an error, but at runtime, casts are still required for dest and SRC.

Difference 2: Type parameters can be multi-qualified but wildcards cannotUse the ampersand symbol to set Multi Bounds, specifying that the generic type T must be a common subtype of MultiLimitInterfaceA and MultiLimitInterfaceB, at which point the variable T has all qualified methods and properties. In the case of wildcards, because it is not a deterministic type, it cannot be multiqualified.

Difference 3: Wildcards can be superclass-qualified while type parameters cannot

The type parameter T has only one kind qualification

T extends A
Copy the code

But wildcards? Two kinds of qualification can be made:

? extends A
? super A
Copy the code

The Class and Class <? > the difference between

That was introduced, right? And T, so for Class and Class<? > < p style = “max-width: 100%; clear: both; min-height: 1em;

The Class and Class <? < p style = “max-width: 100%; clear: both; min-height: 1em;

// Create a multiLimit object by reflection. We need to use cast MultiLimit MultiLimit = (MultiLimit) Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();Copy the code

For the above code at run time, if the reflective type not MultiLimit class, so must be submitted to the Java lang. ClassCastException error.

In this case, you can use the following code instead to check for type problems directly at compile time:

When Class is instantiated, T is replaced by a concrete Class. Class<? > it is a wildcard generic,? Can represent any type, so it is mainly used for declarative restrictions. For example, we could declare:

Public Class<? > clazz; // No, because T needs to specify type public Class<T> classT;Copy the code

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

If you also want to declare public Class classT; In this case, the current class must also specify T

public class Test3<T>{ public Class<? > clazz; public Class<T> classT; }Copy the code