preface
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.
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 be able to predict the actual parameter types.
In the case of a cast error, the compiler may not give an error until runtime, which is itself a security risk.
The advantage of generics, then, 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) {
// doNothing} /** * public void */noSpecifyType(){
GlmapperGeneric glmapperGeneric = new GlmapperGeneric();
glmapperGeneric.set("test"); // The cast String is requiredtest = (String) glmapperGeneric.get();
System.out.println(test); } /** * specifies the type */ public voidspecifyType(){
GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric();
glmapperGeneric.set("test"); // There is no need to cast Stringtest = glmapperGeneric.get();
System.out.println(test); }}Copy the code
SpecifyType methods in this code omit 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 different wildcards, such as T, E, K, V, and so on. What do these wildcards mean?
The usual T, E, K, V?
Essentially, these are wildcards, no difference, just code conventions. For example, in the above code, T can be replaced with any letter between A and Z without affecting the normal operation of the program. However, if T is replaced 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 stands for Element
? Unbounded wildcard
Let’s start with a small example.
https://codeday.me/bug/20180113/116421.html
I have a parent Animal and several subclasses like dog, cat, etc. Now I need a list of animals. My first thought is something like this:
List<Animal> listAnimals
Copy the code
But the boss did have this idea:
List<? extends Animal> listAnimals
Copy the code
Why use wildcards instead of simple generics? Wildcards don’t really mean much when you declare local variables, but they are very important when you declare an argument to 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();
}
returnretVal; } public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); CountLegs (dogs); / / error countLegs1 (dogs); }Copy the code
When countLegs1 is called, it flutters red with the following error message:
So you can use unrestricted wildcards (a question mark in Angle brackets, <? >), indicating that any type can be held. As in countLegs, the last class is qualified, but it doesn’t care what type it is, so all subclasses of Animal passed in can be supported without an error. CountLegs1 doesn’t.
The upper bound wildcard <? extends E>
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 have to 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); / /...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 <? super E>
Lower bound: declared with super, indicating that the parameterized type may be the specified type or a parent of the type, up to Object
Using super in type parameters indicates that the parameters in the generic must be E or a parent of E.
private <T> void test(List<? super T> dst, List<T> src){
for(T t : src) { dst.add(t); } } public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); List<Animal> animals = new ArrayList<>(); new Test3().test(animals,dogs); } class Dog extends Animal {}Copy the code
The DST type is “greater than or equal to” SRC, where “greater than or equal to” means that DST represents a greater range than SRC, so a container that can hold DST can also hold SRC.
? And T
? 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
To summarize briefly:
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 public <T extends Number> voidtest(List<T> dest, List<T> SRC) // Wildcards are indeterminate, so this method does not guarantee that both lists have the same element type public voidtest(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.
There is no guarantee that two lists will have the same element type
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 generate an error from the compiler, but when operating inside testNon methods (such as assignment), the dest and SRC types still need to be cast.
Difference 2: Type parameters can be multi-qualified but wildcards cannot
Use 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 type qualification:
T extends A
Copy the code
But wildcards? Two kinds of qualification can be made:
? extends A
? super A
Copy the code
Class< T > 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 most common use is in reflection scenarios, which are illustrated here with an emission code.
MultiLimit multiLimit = (multiLimit) class.forname ()"com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
Copy the code
For the above code at runtime, 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<? > < span style = “box-sizing: border-box! Important; Can represent any type, so it is mainly used for declarative restrictions. For example, we can declare this:
Public Class<? > clazz; Public Class<T> clazzT;Copy the code
So when you don’t know what type of Class to declare, you can define a Class<? >.
So if you also want to public Class clazzT; In this case, you have to make the current class also specify T,
public class Test3<T> { public Class<? > clazz; Public Class<T> clazzT;Copy the code
This article has pieced together a few points in JAVA generics for your reference. If there are any improper places in the article, please correct them.
reference
https://www.toutiao.com/a6694132392728199683
Author: glmapper
juejin.im/post/5d5789d26fb9a06ad0056bd9
Welcome to follow my wechat public account “Code farming breakthrough”, share Python, Java, big data, machine learning, artificial intelligence and other technologies, pay attention to code farming technology improvement, career breakthrough, thinking transition, 200,000 + code farming growth charge first stop, accompany you have a dream to grow together