Table of Contents
- JAVA type (Type) system
-
- 1. History of the Type System
- 2. Custom tool method
- 3. Various Types
-
- Parameterized type: ParameterizedType
-
- getRawType(): Type
- getOwnerType(): Type
- getActualTypeArguments(): Type[ ]
- GenericArrayType: Generic array type
- TypeVariable: type variable
- WildcardType: wildcard type
- new method for new type
- Generics and type erasure
-
- There are children (Class) first, and then there are parents (Type)
- 1. New methods related to generics
-
- Method’s getGenericParameterTypes method
- Method’s getGenericReturnType method
- Class getGenericSuperclass method
JAVA type (Type) system
1. History of Type System
reminder In fact, there is Class first, and then Type. In other words, Java did not have such a concept as a "type system" at the beginning. It is because after the introduction of the concept of generics, in order to introduce the concept of generics into Java and make backward compatibility, Thus, a Type ancestor and other brothers are "complemented" for Class, thus perfecting the whole system.
In early Java (before 5.0) all types had a Class object, including basic types and custom types:
Student.class Teacher.class String. class Integer.class Double.class Boolean.class int. class int[].class double.class double[].class boolean.class boolean[].class ...
The Class object contains the definition information of the current type, which is the basis of Java reflection. Through a type of Class object, you can query which fields (Field), which methods (Method), which constructors (Constructor) and other information of this type.
However, after JDK 5.0 introduced the concept of generics, Java officials found that some types related to the newly introduced generics do not apply to the sentence we said above that “all types have a Class object”.
“That object” of these generic-related types cannot be classified under the concept of Class object. Their “that object” is both similar to and different from Class objects.
In this regard, Java officially extracted the similarities between them and Class, extracted the concept of Type, and completed other types:
Type ├── Class ├── ParameterizedType ├── TypeVariable ├── WildcardType └── GenericArrayType
Type and its sub-interfaces and implementation classes (Class, ParameterizedType, TypeVariable, WildcardType, GenericArrayType) together form the Java type system.
Now:
All types that have nothing to do with generics have an object of Class type corresponding to them. For example, String type, String[] type.
All types that are related to generics, according to their specific circumstances, have an object of a subtype of the Type type corresponding to them. For example, List
Here’s a more typical example:
The type object of type String[] is Class;
A type object of type List
A type object of type List
2. Custom tool method
In order to detect the specific type of Type more conveniently, we can prepare a simple method as follows:
public static String getTypeName(Type type) {<!-- --> if (type instanceof Class) return "Class"; // just like "String" else if (type instance of TypeVariable) return "TypeVariable"; // just like "T" else if (type instance of ParameterizedType) return "ParameterizedType"; // just like "List<String>"; else if (type instance of GenericArrayType) return "GenericArrayType"; // just like "T[]"; else return "something wrong"; // theoretically shouldn't be }
3. Various types
public class Student<T extends Number> {<!-- --> public List<T> a = new ArrayList<>(); public T b; public List<String>[] c; public T[] d; }
Parameterized type: ParameterizedType
Parameterized types are what we usually call generic types. When it comes to parameters, the most familiar thing is that there are formal parameters when defining a method, and then pass the actual parameters when calling this method.
So how to understand the parameterized type? As the name implies, it is to parameterize the type from the original specific type, similar to the variable parameters in the method. At this time, the type is also defined as a parameter form (which can be called a type parameter), and then the specific type is passed in when using/calling type (type argument).
public static void demoA() {<!-- --> Field aField = null; Field[] fields = Student. class. getDeclaredFields(); for (Field field : fields) {<!-- --> if (field.getName().equals("a")) {<!-- --> aField = field; break; } } ParameterizedType aType = castToParameterizedType(aField. getGenericType()); System.out.println("rawType: " + aType.getRawType()); System.out.println(" ownerType: " + aType.getOwnerType()); for (Type actualTypeArgument : aType. getActualTypeArguments()) {<!-- --> System.out.println("ActualTypeArgument: " + actualTypeArgument); } }
ParameterizedType has 3 common and important methods:
getRawType(): Type
The function of this method is to return the type of the current ParameterizedType. As in a List, what is returned is the Type of the List, that is, the type that returns the remainder of the parameter part without reflection.
If you “seeked” the type at the beginning, you did not call the .getGenericType()
method, but the .getType()
method, .getType()
The type returned by the code> method is this RawType.
getOwnerType(): Type
Some generic classes are inner classes, the most typical being Map.Entry .
The .getOwnerType()
method of the ParameterizedType type returns the type of the outer class where the generic object of the inner class type is located (a mouthful…)
If there is a public Map.Entry
; attribute in Student, call .getOwnerType()
method on it, and the result is Map.
If the generic class is a normal, ordinary class, not an inner class, this method will return null .
getActualTypeArguments(): Type[ ]
The method returns the actual parameter type in the parameterized type <>.
If there is a public Map
in Student; this ParameterizedType
returns an Array of Type objects with fully qualified class names of the String and Date classes.
Note: This method only returns the type in the outermost <>, no matter how many <>s are inside the <>.
In addition, if the type of attribute x is not a definite generic type, but uses generic variables like public List
, then pass getActualTypeArguments()
method, you get the generic variable T.
GenericArrayType: Generic array type
If there is a property such as public T[ ] x or public List
The key method of GenericArrayType is the .getGenericComponentType()
method. It returns the type of the members of this generic array.
In the example above, that’s T and List
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.
Here we know that, theoretically, the type of its constituent elements must be ParameterizedType or TypeVariable.
TypeVariable: type variable
If there is an attribute like public T x in the Student class, the type of the attribute type is TypeVariable.
In addition, as we said earlier, for the attribute public T[] x, its type type is GenericArrayType type, and the type type of its constituent elements is also TypeVariable.
The generic type information will be converted to a specific type at compile time, and TypeVariable is used to reflect the information before the JVM compiles the generic type.
getBounds(): Type[]
Returns the upper bound of the current type, or Object if no upper bound is specified.
getName(): String
Returns the class name of the current type
getGenericDeclaration(): D
Returns the Type of the class the current type is in.
WildcardType: wildcard type
Represents wildcard types, such as >, Extends Number>, etc.
getLowerBounds(): Type[]
Get the array of lower bounds
getUpperBounds(): Type[]
Get the type array of the upper boundary
Note: If no upper bound is specified, it defaults to Object, and if no lower bound is specified, it defaults to String.
New methods for new types
getActualTypeArguments for ParameterizedType
The getGenericSuperclass method of Class returns the generic superclass whose type is Type .
In fact, through the instanceof operator, we can judge that the actual information of the generic parent class is the ParameterizedType type.
The ParameterizedType type has a getActualTypeArguments method that returns the generic parameters used by the generic parent class.
ParameterizedType superclass = (ParameterizedType)StringLinkedList.class.getGenericSuperclass(); for (Type cur : superclass. getActualTypeArguments()) {<!-- --> System.out.println(cur); // only one in this example: String }
Generic types and type erasure
Type is the common parent interface for all types in the Java language. This is the most official explanation.
Class is a direct implementation class of Type. Type and Class, and other subinterfaces (and implementation classes) of Type make up Java’s type system.
There is a child (Class) first, and then a parent (Type)
The Class object contains the definition information of the current type, which is the basis of Java reflection. Through the Class object of a type, you can query information such as which fields, methods, and constructors this type has.
At this time, the Class object of a class “contains” enough relevant information about this class.
For example, for the following class:
public class T1 {<!-- --> public int f1; public int[] f2; }
You can use the reflection method to get information about the two properties of f1 and f2:
T1 x = new T1(); System.out.println(x.getClass().getField("f1")); System.out.println(x.getClass().getField("f2"));
However, after the emergence of the concept of generics, the situation becomes more complicated. For data types involving generics, some original methods (methods that appeared before 1.5) cannot return information in ” Include “generic related information.
For example, if our T1 class from the example above became a generic class:
public class T1<E> {<!-- --> public int f1; public int[] f2; public E[] f3; public Object[] f4; }
Still use the method above.
1. New methods related to generics
Method’s getGenericParameterTypes method
The getGenericParameterTypes method is an upgraded version of the getParameterTypes method.
The function of Method’s getGenericParameterTypes
method is similar to the above getParameterTypes
method, but because it is a “new” method, its return result will retain the generic information.
Still the same method as above:
public static <T> void demo(T arg0, T[] arg1, String arg2) {<!-- --> ... }
The return value of the getGenericParameterTypes
method is an array of Types (not an array of Classes).
Its three elements are
- The first parameter is of type T , of type TypeVariable ;
- The second parameter type is T [ ], the type is GenericArrayType ;
- The third parameter is of type String, of type Class .
Method’s getGenericReturnType method
The getGenericReturnType method is an upgraded version of the getReturnType method
For the same method, Method’s getGenericReturnType
method can identify the generic information of the return value type.
Its return is a T whose type is TypeVariable .
Class getGenericSuperclass method
The getGenericSuperclass function of Class is the same as getSuperclass, but it will retain the generic information of the parent class.
StringLinkedList.class.getGenericSuperclass() // LinkedList<String>