(1). Interface types related to reflection + generics
java.lang.reflect.Type: Common parent interface for all types in the java language
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType
1. Type direct sub-interface
Four types of interfaces: ParameterizedType, GenericArrayType, TypeVariable and WildcardType
ParameterizedType: represents a parameterized type, such as Collection
GenericArrayType: represents an array type whose element type is a parameterized type or type variable
TypeVariable: is the common parent interface for various types of variables
WildcardType: represents a wildcard type expression, such as ?, ? extends Number, ? super Integer [wildcard is a word: it is "wildcard"]
2. Type directly implements subclasses: Class class
3. java.lang.reflect.Type interface
All types of Type refer to: raw types (raw types) [corresponding to Class], parameterized types (parameterized types) [corresponding to ParameterizedType], array types (array types) [corresponding to GenericArrayType], type variables (type variables) [corresponding to TypeVariable ], basic data types (primitivetypes) [still corresponding to Class]
4. java.lang.reflect.ParameterizedType interface
The meaning of ParameterizedType interface type
Represents a parameterized type. For example: a parameterized type like Map
Get the actual type in parameterized type<>
Source code statement: Type[] getActualTypeArguments();
[Note] No matter how many levels of <> nesting there are in <>, this method only removes the outermost <> and the remaining content is used as the return value of this method.
public static E methodIV(
ArrayList> al1,
ArrayList al2,
ArrayList al3,
ArrayListextends Number> al4,
ArrayList al5){}
Then each of its parameters is generally of parametric type.
{1}. For ArrayList>, after returning through getActualTypeArguments(), after removing the outermost <>, the remaining type is ArrayList. Therefore the return type for this parameter is ParameterizedType.
{2}. For ArrayList, after returning through getActualTypeArguments(), after removing the outermost <>, the remaining type is E. Therefore the return type for this parameter is TypeVariable.
{3}. For ArrayList, after returning through getActualTypeArguments(), after removing the outermost <>, the remaining type is String. Therefore the return type for this parameter is Class.
{4}. For ArrayListextends Number>, after returning through getActualTypeArguments(), after removing the outermost <>, the remaining type is? ExtendsNumber. Therefore the return type for this parameter is WildcardType.
{5}. For ArrayList, after returning through getActualTypeArguments(), after removing the outermost <>, the remaining type is E[]. Therefore the return type for this parameter is GenericArrayType.
Therefore, it is possible to obtain actual parameters of various types, so for the sake of unification, the direct parent class array Type[] is used for reception.
4. java.lang.reflect.GenericArrayType interface
The meaning of GenericArrayType interface type
Represents a generic array type. For example: void method(ArrayList[] al){…}
[Note] <> cannot appear in the initialization of the array, that is, <> cannot appear after the new array, otherwise javac will not pass. But it is completely fine as a reference variable or a parameter of a method.
Get the type of elements in a generic array
Source code declaration: Type getGenericComponentType();
[Note] No matter how many [] are juxtaposed from left to right, this method only removes the rightmost [] and the remaining content is used as the return value of this method.
Why is the return value type Type?
public static E methodV(String[] p1,E[] p2,ArrayList[] p3,E[][] p4){}{1}. For String[], after returning through getComponentType(), after removing the rightmost [], the remaining type is String. Therefore the return type for this parameter is Class
{2}. For E[], after returning through getComponentType(), after removing the rightmost [], the remaining type is E. Therefore the return type for this parameter is TypeVariable
{3}. For ArrayList[], after returning through getComponentType(), after removing the rightmost [], the remaining type is ArrayList. Therefore the return type for this parameter is ParameterizedType
{4}. For E[][], after returning through getComponentType(), after removing the rightmost [], the remaining type is E[]. Therefore the return type for this parameter is GenericArrayType
5. java.lang.reflect.GenericArrayType interface
The meaning of TypeVariable interface type
Represents type parameters or also called type variables. For example: E in void method(E e){} is the type variable
Gets the type of the generic-qualified upper bound of a type variable
Source code statement: Type[] getActualTypeArguments();
[Note] This is just the upper boundary. The reason is that type variables can only use extends to limit (multiple) boundaries when they are defined. Super cannot be used, otherwise the compilation will not pass. At the same time, extends gives the upper bound of type variables.
Why is the return type an array? Because type variables can be qualified with multiple upper bounds by &, there are multiple upper bounds, so the return value type is the array type [].
For example the following method:
public static extends Map& Cloneable&Serializable> E methodVI(E e){…}The first upper boundary of E is Map, which is a ParameterizedType type
The second upper boundary of E is Cloneable, which is of Class type
Therefore, for unification, the element type of the array of return values is Type
6. java.lang.reflect.WildcardType interface
The meaning of WildcardType interface type
An expression representing a wildcard type.
For example, void printColl(ArrayListal); in ? extends Number
[Note] According to the comments of the above API: at this stage, the wildcard expression only accepts an upper boundary or a lower boundary. This is different from when defining a type variable, which can specify multiple upper boundaries. But the API said that in order to maintain scalability, the return value type here is written in array form. In fact, the size of the array returned now is 1
Gets the type of the generic-qualified upper bound of a wildcard expression object
Source code statement: Type[] getUpperBounds();
[Note] As mentioned above, the size of the array in Type[] returned at this stage is 1. Written as Type[ ] is an extension for language upgrade.
For example the following method:
{1}. public static voidprintColl(ArrayListextends ArrayList> al){}
The wildcard expression is: ? extendsArrayList, so that extends is followed by the upper boundary of ?, and this upper boundary is the ParameterizedType type.
{2}. public static voidprintColl(ArrayListextends E> al){}
The wildcard expression is: ? extends E, so that extends is followed by the upper boundary of ?, and this upper boundary is the TypeVariable type
{3}.public static voidprintColl(ArrayListextends E[]> al){}
The wildcard expression is: ? extends E[], so that extends is followed by the upper boundary of ?, and this upper boundary is of GenericArrayType type
{4}.public static voidprintColl(ArrayListextends Number> al){}
The wildcard expression is: ? extends Number, so that extends is followed by the upper boundary of ?, and this upper boundary is the Class type
Finally unified into Type as the element type of the array.
7. The origin of Type and its sub-interfaces
1. Types before the emergence of generics
When there are no generics, there are only so-called primitive types. At this time, all primitive types are abstracted through the bytecode file class Class class. A concrete object of the Class class represents a specified primitive type.
2. Types after the emergence of generics
After the emergence of generics, data types were expanded. From only primitive types, parameterized types, type variable types, generic-qualified parameterized types (including wildcards + wildcard-qualified expressions), and generic array types have been expanded.
3. The reason why types related to generics cannot be unified with original types into Class
[1]. [Cause of generic erasure]
Originally, the newly generated types + primitive types should be unified into their respective bytecode file type objects. But since generics were not originally an ingredient in Java. If generics are really added, it involves modification of the JVM instruction set, which is very fatal.
[2]. [How to introduce generics in Java]
In order to take advantage of generics without actually introducing them, Java uses a generic erasure mechanism to introduce generics. Generics in Java are only used by the compiler javac to ensure data security and avoid the trouble of forced type conversion. However, once compilation is complete, all types related to generics are erased.
[3]. [Class cannot express types related to generics]
Therefore, parameterized types related to generics, type variable types, generic-qualified parameterized types (including wildcards + wildcard-qualified expressions), and generic array types are all returned to their original forms and are stored in the bytecode file. All are original types after generics have been erased, and there is no bytecode file consistent with its own type. Therefore, newly expanded types related to generics cannot be unified into the Class class.
(4). Representation of types related to generics in Java
In order to operate these types through reflection to meet the needs of actual development, Java has added ParameterizedType, GenericArrayType, TypeVariable and WildcardType to represent types that cannot be classified into the Class class but have the same name as the original type.
(5). Introduction of Type: unifying types related to generics and primitive types Class
[Reason for introducing Type]
For the scalability of the program, the Type interface was finally introduced as the general parent interface for Class, ParameterizedType, GenericArrayType, TypeVariable and WildcardType. In this way, the Type type parameter accepts the actual parameters of the above five subtypes or the return value type is the Type type parameter.
[The reason why there is no method in the Type interface]
As can be seen from the above, the emergence of Type only plays the role of improving program scalability through polymorphism, and has no other effect. Therefore, there are no methods in the source code of the Type interface.