Java Type类及其子类用途

Type

Type类为Java所有类型的通用接口

  public interface Type {
    default String getTypeName() {
        return toString();
    }
}

查看他的继承关系:
包括原始类型、参数化类型(Parameterized)、数组类型(GenericArrayType)、类型变量(TypeVariable)、通配符类型(WildcardType)和基本类型(Class<T>);

接下来分开查看对应子类源码和测试其用法;

Parameterized

/**
 *  参数化类型也就是我们常用的泛型比如List<T>等带泛型的都属于此类型
 */
public interface ParameterizedType extends Type {
    //获取参数化类型参数;比如Map<K,V>;那么返回,K/V对应数组;
    Type[] getActualTypeArguments();
    //获取原始类型,泛型💰类型,例如:List<T> 中为 List
    Type getRawType();
    //如果是内部类,获取拥有内部类的外部类例如Map.Entry<K,V>中应该为Map
    Type getOwnerType();
}

测试一下:

public class ParameterizedTypeTest {
    private Map.Entry<String, Integer> entry = null;

    public static void main(String[] args) {
        try {
            Field fieldList = ParameterizedTypeTest.class.getDeclaredField("entry");
            Type listType = fieldList.getGenericType();
            ParameterizedType listParameterizedType = (ParameterizedType) listType;
            Type[] listActualTypeArguments = listParameterizedType.getActualTypeArguments();
            Type listRawType = listParameterizedType.getRawType();
            Type listOwnType = listParameterizedType.getOwnerType();
            for (Type type : listActualTypeArguments) {
                System.out.println("listActualTypeArguments:" + type.getTypeName());
            }
            System.out.println("listRawType:" + listRawType.getTypeName());
            System.out.println("listOwnType:" + listOwnType.getTypeName());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

得到下面的输出结果:

listActualTypeArguments:java.lang.String
listActualTypeArguments:java.lang.Integer
listRawType:java.util.Map$Entry
listOwnType:java.util.Map

GenericArrayType

数组泛型类型;
查看源码:

/**
* 大致应该存在两种类型int[],List<String>[];
*/
public interface GenericArrayType extends Type {
    //可以获取到数组前面的类型,比如:List<String>[]为List<String>
    Type getGenericComponentType();
}

看示例:

public class GenericArrayTypeTest<T> {
    private T[] intArrays = null;
    private List<String>[] listArrays = null;

    public static void main(String[] args) {
        try {
            Field intFiled = GenericArrayTypeTest.class.getDeclaredField("intArrays");
            Type intType = intFiled.getGenericType();
            GenericArrayType intGenericArrayType = (GenericArrayType) intType;
            System.out.println("intType:" + intType.getClass().getName());
            System.out.println("intGenericArrayType:" + intGenericArrayType.getGenericComponentType().getTypeName());

            Field listFiled = GenericArrayTypeTest.class.getDeclaredField("listArrays");
            Type listType = listFiled.getGenericType();
            GenericArrayType listGenericArrayType = (GenericArrayType) listType;
            System.out.println("listType:" + listType.getClass().getName());
            Type listCompinentType = listGenericArrayType.getGenericComponentType();
            System.out.println("listCompinentType:" + listCompinentType.getTypeName());
            System.out.println("listCompinentTypeClass:" + listCompinentType.getClass().getName());

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

打印结果:

intType:sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
intGenericArrayType:T
listType:sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
listCompinentType:java.util.List<java.lang.String>
listCompinentTypeClass:sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl

TypeVariable

类型变量:

/**
* 真实泛型变量值:例如List<T>中的T;
*/
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    //获得该类型变量的上限,也就是泛型中extend右边的值;
     //例如 List<T extends Number> ,Number就是类型变量T的上限;
    Type[] getBounds();
    //获取声明该类型变量实体
    D getGenericDeclaration();

    String getName();

    AnnotatedType[] getAnnotatedBounds();
}

不明白直接看示例:

public class TypeVariableTest<T extends Number> {
    private Map<String, T> map = null;

    public static void main(String[] args) {
        try {
            Field mapField = TypeVariableTest.class.getDeclaredField("map");
            Type mapType = mapField.getGenericType();
            System.out.println("mapType:" + mapType.getClass().getName());
            ParameterizedType mapParameterizedType = (ParameterizedType) mapType;
            Type[] mapParameterizedTypes = mapParameterizedType.getActualTypeArguments();
            for (Type mapParamType : mapParameterizedTypes) {
                System.out.println("mapParamType:" + mapParamType.getClass().getName());
                if (mapParamType instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) mapParamType;
                    System.out.println("typeVariable:" + typeVariable.getGenericDeclaration().toString());
                    for (Type boundsType : typeVariable.getBounds()) {
                        System.out.println("boundsType:" + boundsType.getTypeName());
                    }
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

打印结果:

mapType:sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
mapParamType:java.lang.Class
mapParamType:sun.reflect.generics.reflectiveObjects.TypeVariableImpl
typeVariable:class com.xxx.lib.TypeVariableTest
boundsType:java.lang.Number

WildcardType

通配符类型;

/**
* 通配符类型;例如:List<? extends Number>
*/
public interface WildcardType extends Type {
    //获取上边界List<? extends Number> Number
    Type[] getUpperBounds();
    //获取下边界List<? super String> String
    Type[] getLowerBounds();
}

看示例:

public class WildcardTypeTest {
    private List<? extends Number> numbers;

    public static void main(String[] args) {
        try {
            Field numField = WildcardTypeTest.class.getDeclaredField("numbers");
            Type numType = numField.getGenericType();
            System.out.println("numType:" + numType.getClass().getName());
            ParameterizedType numsParameterizedType = (ParameterizedType) numType;
            for (Type actualType : numsParameterizedType.getActualTypeArguments()) {
                System.out.println("actualType:" + actualType.getClass().getName());
                WildcardType wildcardType = (WildcardType) actualType;
                Type[] uppperBounds = wildcardType.getUpperBounds();
                if (uppperBounds != null) {
                    for (Type upper : uppperBounds) {
                        System.out.println("upper:" + upper.getTypeName());
                        System.out.println("upper Type:" + upper.getClass().getName());
                    }
                }
                Type[] lowerBounds = wildcardType.getLowerBounds();
                if (lowerBounds != null) {
                    for (Type lower : lowerBounds) {
                        System.out.println("lower:" + lower.getTypeName());
                        System.out.println("lower Type:" + lower.getClass().getName());
                    }
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

输出结果:

numType:sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
actualType:sun.reflect.generics.reflectiveObjects.WildcardTypeImpl
upper:java.lang.Number
upper Type:java.lang.Class

现实应用,Retrofit的returnType是如何拿到的?

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();
          private final Object[] emptyArgs = new Object[0];

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //将method传递到后面
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

loadServiceMethod调用HttpServiceMethod

private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      CallAdapter<ResponseT, ReturnT> callAdapter,
      Converter<ResponseBody, ResponseT> responseConverter) {
    this.requestFactory = requestFactory;
    this.callFactory = callFactory;
    this.callAdapter = callAdapter;
    this.responseConverter = responseConverter;
  }

  @Override ReturnT invoke(Object[] args) {
    //这里调用了callAdapter,继续跟进callAdapter
    return callAdapter.adapt(
        new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
  }

····

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
      Retrofit retrofit, Method method) {
    //这里可以看到从method上拿到了返回类型的returnType;但是这里我们通常都是Observable<xxx>,最终传递给Converter的类型应该继续查看
    Type returnType = method.getGenericReturnType();
    Annotation[] annotations = method.getAnnotations();
    try {
      //可以看到这里直接调用了retrofit的callAdaper;这是使我们初始化的retrofit设置的CallAdapter
      return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }

直接追下RxJava2CallAdapterFactory

@Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //这里有个获取真实类型的,看名字这里应该是我们需要找的,等会进入这个类再详细的解释
    Class<?> rawType = getRawType(returnType);
  //删除部分无关代码
    .......
    
    Type responseType;
    //这里可以看到 会判断返回类型是不是参数化类型。不是直接返回,这里必须是Observable<?>、Flow<?>等,将我们上面的学习,是ParameterizedType,我们学习结果得到了验证
    if (!(returnType instanceof ParameterizedType)) {
      String name = isFlowable ? "Flowable"
          : isSingle ? "Single"
          : isMaybe ? "Maybe" : "Observable";
      throw new IllegalStateException(name + " return type must be parameterized"
          + " as " + name + "<Foo> or " + name + "<? extends Foo>");
    }
    //// getParameterUpperBound到下面详细介绍
    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
    Class<?> rawObservableType = getRawType(observableType);
    if (rawObservableType == Response.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Response must be parameterized"
            + " as Response<Foo> or Response<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
    } else if (rawObservableType == Result.class) {
      if (!(observableType instanceof ParameterizedType)) {
        throw new IllegalStateException("Result must be parameterized"
            + " as Result<Foo> or Result<? extends Foo>");
      }
      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
      isResult = true;
    } else {
      responseType = observableType;
      isBody = true;
    }

    return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
        isSingle, isMaybe, false);
  }

接下来我们看看getParameterUpperBound 和getRawType方法,他们最终调用Util中的方法,直接看对应方法

static Class<?> getRawType(Type type) {
    checkNotNull(type, "type == null");

    if (type instanceof Class<?>) {
      // 如果是class直接返回
      return (Class<?>) type;
    }
    if (type instanceof ParameterizedType) {
  //如果是参数化类型
      ParameterizedType parameterizedType = (ParameterizedType) type;
      //拿到真实类型比如Observable<?> 拿到Observable;
      Type rawType = parameterizedType.getRawType();
      if (!(rawType instanceof Class)) throw new IllegalArgumentException();
      return (Class<?>) rawType;
    }
    if (type instanceof GenericArrayType) {
      Type componentType = ((GenericArrayType) type).getGenericComponentType();
    //如果是数组类型,通过Array.newInstance得到数组对象,然后拿到对应的class
      return Array.newInstance(getRawType(componentType), 0).getClass();
    }
    if (type instanceof TypeVariable) {
    //type直接是类型变量,这里直接返回了Object.class;我们可以根据边界继续寻找
      return Object.class;
    }
    if (type instanceof WildcardType) {
    //如果是通配符类型,拿到上边界类型,有可能有多个层级,继续调用getRawType
      return getRawType(((WildcardType) type).getUpperBounds()[0]);
    }

    throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
          + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
  }

static Type getParameterUpperBound(int index, ParameterizedType type) {
 //这个很简单就是获取对应泛型参数位置类型,如果是通配符类型拿上边界    
Type[] types = type.getActualTypeArguments();
    if (index < 0 || index >= types.length) {
      throw new IllegalArgumentException(
          "Index " + index + " not in range [0," + types.length + ") for " + type);
    }
    Type paramType = types[index];
    if (paramType instanceof WildcardType) {
      return ((WildcardType) paramType).getUpperBounds()[0];
    }
    return paramType;
  }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • [TOC] 学习之中涉及到了,找了几片文章学习了以下,这里做个记录: ParameterizedType参数化类型...
    mecury阅读 546评论 0 0
  • 上一篇,提到了Java-Type体系,对Type类型进行了简单的讲解;本篇,就用代码的方式,对其中的5大类型:原始...
    贾博岩阅读 13,937评论 15 54
  • 前言 Type体系的引入是对泛型的一种补偿。java泛型的引入为编译器提供了更严格的代码审查,但这些泛型信息在运行...
    好多个胖子阅读 1,641评论 0 7
  • Type类型 Type是接口,它的实现类(子接口)有Class, ParameterizedType, Wildc...
    kevin1985阅读 413评论 0 0
  • 参考 Java中的Type Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有...
    WangGavin阅读 8,872评论 6 15