美文网首页
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类及其子类用途

    Type Type类为Java所有类型的通用接口 查看他的继承关系:包括原始类型、参数化类型(Parameteri...

  • Java 异常关键点

    不是Throwable的子类,不能catch Error及其子类 Error类表示Java运行时产生的系统内部错误...

  • Android面试知识点(二)*

    1、java常见的异常: 分为Error和Exception,都是继承于Throwable。 Error类及其子类...

  • scala 调用java通过父类调用子类方法实现

    scala 调用java通过父类调用子类方法实现 java 父类 A 抽象类: java 子类 B 继承A类,并...

  • JVM

    java类加载机制? JVM的类加载是通过ClassLoader及其子类来完成的,虚拟机把描述类的数据从Class...

  • ViewAnimator

    android视图切换动画:ViewAnimator类及其子类

  • Reference、ReferenceQueue

    关于Java源码的学习可以参考《Java源码分析》:ReferenceQueue、Reference及其子类。这里...

  • Java泛型之Type

    1、Type Type是一个接口,是所有类型的父类,下图展示了Type的继承结构: 可以看到Type的子类有如下几...

  • python学习-type(),isinstance(),dir

    isinstance() 与 type() 区别:type() 不会认为子类是一种父类类型,不考虑继承关系。isi...

  • NO.22 Final关键字概述与使用

    final关键字的概述 1、修饰类,类不能被继承 ( The type 子类 cannot subclass t...

网友评论

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

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