In my opinion, JDK5.0 is definitely a landmark version. In this version, it provides a lot of valuable new features, generics is one of them, and the reflection mechanism is enhanced. , and version 5.0 also reconstructed the previous collection framework and added generic support.
It has been almost 10 years since the release of 5.0. There is a lot of knowledge about this aspect available online and also in books. Elephant is writing these things now, firstly, to summarize his own experience and experience, and secondly, in the hope of giving some help to children who are new to this aspect.
The biggest benefit of generics is type checking, which is especially useful for collections. It is also very useful in underlying code design, as it enables reuse. There are two ways to define generics, one is a generic class and the other is a generic method.
So what exactly are generics? To put it simply (maybe not rigorously), it means that type variables such as type parameters are used. Whether it is a class, interface or method, it can be said that generics are used. See the example:
Generic class
use ’s ’ using ’s ’ using through using using’’ out out out out out out out out out of ’s ’ ’s ’ ’ through through through out through out through through through‐‐‐‐‐‐‐ public void setT(T t) {
this.t = t;
. A generic class can have multiple type variables defined. Type variables are generally represented by a capital letter, such as Person
It is possible to instantiate a generic class by replacing the type variable with a concrete class: Person
It is wrong to instantiate like this: Person
Generic method
public
I defined a method in the MyBatisDao class in the SSM3 example. This method is a generic method.
But if I rewrite it and add generics to MyBatisDao, public class MyBatisDao
Then there will be a compilation error in the return type of User:
Based on the Role type variable MyBatisDao
Limitation of type parameters
The range represented by type variables like
Upper limit:
Lower limit: super T>
The question mark (?) is called an unlimited wildcard, It can represent any type. Sometimes it is not so convenient to use type variables, and wildcard types solve this problem very well.
super T> It can be understood that the super type of any T type variable also includes T itself, because T can be regarded as a super type of itself.
Then why is it said that extends is the upper limit and extends is the lower limit? It should be obvious from the previous two explanations that extends Serializable or extends T indicates that the type variable must be a subclass of Serializable and a subtype of the T variable. Is this equivalent to limiting the upper limit of the type variable? In the same way, we can understand the meaning of the lower limit.
Having said so much about upper and lower limits, what is their use? and how to use it? Simply put, type parameters qualified by extends can be read from generic objects, and type parameters qualified by super can be written to generic objects. Saying this may make some children faint. What the hell is this talking about?
Let’s put it another way. A formula has been summarized about the upper and lower limits of generics: PECS
PECS means producer-extends, consumer-super
The above means that if the parameterized type represents a producer, use < ? extends T>, if it represents a consumer, use super T>. Let’s understand it together with the above explanation. Is it clear? If you still don’t understand it well, Elephant attaches a short piece of code to understand the difference.
Public void add(List extends T> list){
for(T t : list){
} add(t);
}
}
Public void add(T t){};
public void add(T t, List super T> list){
List.add(t);
}
Generic erasure
Generics are mainly valid during compilation, that is, type safety is checked during compilation. Nowadays, when writing code, it is generally Using Eclipse or IntelliJ, these integrated development tools can compile on-the-fly, and a red error mark will appear immediately if there is an error. So if a type conversion error occurs, the result will be obvious. However, during the running stage of the program, the JVM does not recognize that generics are magic. All classes, interfaces, and methods with generics will have their generics erased and become raw types, that is, Person< T> becomes Person, List extends T> list becomes List list, etc.
The following is the result of decompiling the previous Person class with javap. All type variables T have been erased. Because T is an unqualified type, it is replaced with Object. Moreover, extends T> and super T> in the add method have also been removed.
public class com.bolo.Person extends java.lang.Object{
private java.lang.Object t;
public com.bolo.Person();
public java.lang.Object getT();
public void setT(java.lang.Object);
public void add(java.util.List);
public void add(java.lang.Object);
public void add(java.lang.Object, java.util. List);
}
Therefore, for the feature of generic erasure, we need to pay attention to the following points:
1. There are no generics in the JVM, only ordinary classes and methods.
2. All type parameters are replaced with limited types or unrestricted types with Object.
3. Please handle method overloading with caution. Wrong use of overloading will not achieve the desired polymorphism.
4. To ensure type safety, please use forced type conversion when necessary.
Limitations of generics
Basic types cannot be used as type parameters. Person
Type checking can only use primitive types. if(t instanceof Person) If written as if(t instanceof Person
Type variables cannot be instantiated. It is wrong to write this: T t = new T()
You cannot instantiate an array of parameterized types. Person
Static instance variables and static methods cannot be defined. If you want to write like this: private static T a Then I'm sorry, the compiler will give you an error message immediately.
In fact, there is no need to talk about the restrictions on generics. Compilers are very powerful now. As long as you do this, an error will be displayed to you immediately.
Finally, generics are the most useful for collections. A collection is a container, and generics make it easier to reuse. The collection we use most frequently is the List, and the other container is the array. Elephant strongly recommends that you use List more and try not to use arrays. The first is that List has type safety checks, the second is that List provides all the functions of arrays and is richer, and the third is that List optimizes gc. If you use arrays, especially operating object arrays, if you are inexperienced and do not release the object references in the array, it is easy to cause memory leaks.
For more generic articles related to the summary of the use of generics and reflection, please pay attention to the PHP Chinese website!