Type 体系
Class
这个我们是最常见的。我们经常会问某个对象/变量是什么类型、我们经常回答都是对应一个具体的 Class
public class ClassMain {
private Integer age;
private String name;
private List<String> alias;
public static void main(String[] args) {
ClassMain classMain = new ClassMain();
System.out.println("classMain 这个变量的类型:" + classMain.getClass());
Field[] declaredFields = classMain.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + ":" + declaredField.getType());
}
}
}
classMain 这个变量的类型:class com.example.junitspringboot.type.ClassMain
age:class java.lang.Integer
name:class java.lang.String
alias:interface java.util.List
为啥变量 alias
的输出只有List
而不包含 String
的,这个就是下面要说的内容
ParameterizedType
参数化类型、这个也是我们最常见的。
public interface ParameterizedType extends Type {
// 获取实际的参数类型
Type[] getActualTypeArguments();
// 获取原始的类型
Type getRawType();
// 针对内部类、返回其外层的类型
Type getOwnerType();
}
从类/成员变量获取
就如上面的例子、alias
的类型就是 parameterizedType 而不是简单的 Class
我们可以通过另一种方法获取 getGenericType
public class ClassMain {
private Integer age;
private String name;
private List<String> alias;
public static void main(String[] args) {
ClassMain classMain = new ClassMain();
System.out.println("classMain 这个变量的类型:" + classMain.getClass());
Field[] declaredFields = classMain.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField.getName() + ":" + declaredField.getGenericType());
}
}
}
// java.lang.reflect.Field#getGenericType
public Type getGenericType() {
if (getGenericSignature() != null)
return getGenericInfo().getGenericType();
else
return getType();
}
public Class<?> getType() {
return type;
}
可以看到 getType 方法返回的是 Class 而 getGenericType 返回的是 Type 类型
classMain 这个变量的类型:class com.example.junitspringboot.type.ClassMain
age:class java.lang.Integer
name:class java.lang.String
alias:java.util.List<java.lang.String>
我们稍微改下程序
public class ClassMain {
private Integer age;
private String name;
private List<String> alias;
public static void main(String[] args) {
ClassMain classMain = new ClassMain();
System.out.println("classMain 这个变量的类型:" + classMain.getClass());
Field[] declaredFields = classMain.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
Type type = declaredField.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {
System.out.println(declaredField.getName() + " getActualTypeArguments:" + actualTypeArgument);
}
System.out.println(declaredField.getName() + " getOwnerType:" + parameterizedType.getOwnerType());
System.out.println(declaredField.getName() + " getRawType:" + parameterizedType.getRawType());
} else if (type instanceof Class) {
System.out.println(declaredField.getName() + ":" + type);
}
}
}
}
classMain 这个变量的类型:class com.example.junitspringboot.type.ClassMain
age:class java.lang.Integer
name:class java.lang.String
alias getActualTypeArguments:class java.lang.String
alias getOwnerType:null
alias getRawType:interface java.util.List
那方法内的局部变量呢?还有方法的参数呢、他们如果声明变量的时候带有泛型信息、怎么获取得到呢、他们只能使用变量然后调用 getClass 方法、没错、Java 中擦除了、因为 Java 的泛型只是一个语法糖、只保留类、Field、Method 的泛型信息
增加一个内部类的成员变量
static class Holder<T> {
private T data;
}
private Holder<String> holder;
holder getActualTypeArguments:class java.lang.String
holder getOwnerType:class com.example.junitspringboot.type.ClassMain
holder getRawType:class com.example.junitspringboot.type.ClassMain$Holder
可以看到 getOwnerType 不再返回 null 了
从类中获取
public class Msg<T> {
private T data;
}
public class StringMsg extends Msg<String>{
}
Type genericSuperclass = StringMsg.class.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
System.out.println(parameterizedType.getRawType());
System.out.println(parameterizedType.getOwnerType());
for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) {
System.out.println(actualTypeArgument.getTypeName());
}
}
class com.example.junitspringboot.type.Msg
null
java.lang.String
可以看到子类继承 Msg 类的时候传递了 String 作为参数给到父类。让父类成为参数化类型。
从方法中获取
public class StringMsg extends Msg<String>{
List<String> process(){
System.out.println();
return null;
}
}
Method[] declaredMethods = StringMsg.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
Type genericReturnType = declaredMethod.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
System.out.println(((ParameterizedType) genericReturnType).getActualTypeArguments()[0]);
System.out.println(((ParameterizedType) genericReturnType).getRawType());
}
}
class java.lang.String
interface java.util.List
TypeVariable
泛型的类型变量,指的是List< T>、Map< K,V>中的T,K,V等值,实际的Java类型是TypeVariable
static class Holder<T extends String & Serializable> {
private T data;
public T getData() {
return data;
}
}
static class SonHolder<T extends String> extends Holder<T>{
}
private static void typeVariable() throws NoSuchFieldException, NoSuchMethodException {
Field data = Holder.class.getDeclaredField("data");
Type genericType = data.getGenericType();
if (genericType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) genericType;
System.out.println(typeVariable.getName());
}
Method getData = Holder.class.getDeclaredMethod("getData");
Type genericReturnType = getData.getGenericReturnType();
if (genericReturnType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) genericReturnType;
System.out.println(typeVariable.getName());
}
Type genericSuperclass = SonHolder.class.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
Type actualTypeArgument = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
if (actualTypeArgument instanceof TypeVariable) {
System.out.println(((TypeVariable) actualTypeArgument).getName());
Type[] bounds = ((TypeVariable) actualTypeArgument).getBounds();
System.out.println();
}
}
}
类型变量的上限可以为多个,必须使用&符号相连接,例如 List< T extends Number & Serializable>;其中,& 后必须为接口;
WildcardType
通配符表达式,或泛型表达式,它虽然是Type的一个子接口,但并不是Java类型中的一种,表示的仅仅是类似 ? extends T、? super K这样的通配符表达式。 ?—通配符表达式,表示通配符泛型,但是WildcardType并不属于Java-Type中的一种
static class Holder<T extends String & Serializable> {
private T data;
List<?> list;
public T getData() {
return data;
}
}
private static void wildcardType() throws Exception {
Field list = Holder.class.getDeclaredField("list");
Type genericType = list.getGenericType();
if (genericType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
if (actualTypeArguments[0] instanceof WildcardType) {
WildcardType wildcardTypes = (WildcardType) actualTypeArguments[0];
System.out.println(wildcardTypes.getUpperBounds()[0].getTypeName());
}
}
}
GenericArrayType
泛型数组 泛型数组,描述的是形如:A< T>[]或T[]类型变量和原始类型
/**
* 含有泛型数组的才是GenericArrayType
* @param pTypeArray GenericArrayType type :java.util.List<java.lang.String>[];
* genericComponentType:java.util.List<java.lang.String>
* @param vTypeArray GenericArrayType type :T[];genericComponentType:T
* @param list ParameterizedType type :java.util.List<java.lang.String>;
* @param strings type :class [Ljava.lang.String;
* @param test type :class [Lcom.wangji.demo.GenericArrayTypeTest;
*/
public void testGenericArrayType(List<String>[] pTypeArray, T[] vTypeArray
, List<String> list, String[] strings, GenericArrayTypeTest[] test) {
}
/**
* 1、getGenericComponentType
* 返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)
* 、T[] 中的T(TypeVariableImpl);
* 值得注意的是,无论是几维数组,getGenericComponentType()方法都只会脱去最右边的[],返回剩下的值;
*/
Spring 中的 ResolvableType
建议使用 ResolvableType 、最近封装公司的 RPC 通信模块、子类通过继承的方式将泛型信息传递到父类、这个时候获取到完整的泛型信息显得非常重要、后续 RPC 返回的信息反序列化为对应的实体。
public class T1<T> {
}
public class T2<T> extends T1<List<T>> {
}
public class T3 extends T2<Map<String,Integer>> {
}
简化之后类似如上、我们怎么在 T1 中获取到正确的 Type 类型、且该 Type 能用于反序列化。