Home  >  Article  >  Java  >  Summary of the use of generics and reflection - Generics

Summary of the use of generics and reflection - Generics

高洛峰
高洛峰Original
2016-12-19 15:39:001574browse

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 in this example, List in JDK, Map, etc.
It is possible to instantiate a generic class by replacing the type variable with a concrete class: Person person = new Person();
It is wrong to instantiate like this: Person person = new Person (); //ERROR
Generic method


public T get(String key, Object params) {
I defined a method in the MyBatisDao class in the SSM3 example. This method is a generic method. is the type variable, and the T in front of get is the return type. In fact, this method has type safety issues. If I call this method in RoleService and write the return type T as User, the compiler will not give any warning message.
But if I rewrite it and add generics to MyBatisDao, public class MyBatisDao extends SqlSessionDaoSupport
Then there will be a compilation error in the return type of User:

Based on the Role type variable MyBatisDao, the compiler will infer that the get method defined in it should return the Role type. However, after this change, MyBatisDao becomes a generic class, and the get method is no longer a generic method. So can generic methods have safety checks? Yes, but it requires some programming skills. The key is related to the generic method you write. The restrictions on type parameters mentioned later can restrict generics and solve some security check problems.
Limitation of type parameters
The range represented by type variables like is sometimes too large, and sometimes it is inconvenient to use. For example, now we need to implement a generic class that implements the java.io.Serializable interface, so how should we do this? The JDK experts designed something called "restricted wildcard type" for us to solve this problem. Generally we call them upper limit and lower limit. They are usually written as follows:
Upper limit: or
Lower limit:
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.
means that T is a class that implements the Serializable interface, T is a subtype of the binding type (Serializable), and T and the binding type can be an interface or a class. If you want to add another restriction that implements the Comparable interface, you only need to write it like this: This writing is a bit loose, because the Comparable interface is a generic interface that can receive generic parameters. We will not discuss this now. Complex situation.
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 . 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 list){
for(T t : list){
} add(t);
}
}
Public void add(T t){};
public void add(T t, List 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 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, and 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 is wrong, you can only use Person
Type checking can only use primitive types. if(t instanceof Person) If written as if(t instanceof Person), a compilation error will appear immediately
Type variables cannot be instantiated. It is wrong to write this: T t = new T()
You cannot instantiate an array of parameterized types. Person[] p = new Person[5] //ERROR
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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn