美文网首页
Java Type类及其子类用途

Java Type类及其子类用途

作者: DustMoon | 来源:发表于2021-01-26 18:43 被阅读0次

    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;
      }
    

    相关文章

      网友评论

          本文标题:Java Type类及其子类用途

          本文链接:https://www.haomeiwen.com/subject/thggzktx.html