Java 泛型之type

2018-08-31  本文已影响22人  PuHJ

一、泛型的好处

简单的说,

二、类型变量命名约定

三、泛型体系

Type体系
(1)、Type接口

官方的解释:Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

/**
 * Type is the common superinterface for all types in the Java
 * programming language. These include raw types, parameterized types,
 * array types, type variables and primitive types.
 *
 * @since 1.5
 */
public interface Type {
    /**
     * Returns a string describing this type, including information
     * about any type parameters.
     *
     * @implSpec The default implementation calls {@code toString}.
     *
     * @return a string describing this type
     * @since 1.8
     */
    default String getTypeName() {
        return toString();
    }
}

从图中可以看出Type的四大子接口,它们分别代表不同的类型:

泛型多是在框架中应用比较多,如Retrofit框架中的源码,该方法的大体意思就像是获取List<String>中的最外层的List类型。

  static Class<?> getRawType(Type type) {
    if (type == null) throw new NullPointerException("type == null");

    if (type instanceof Class<?>) {
      // Type is a normal class.
      return (Class<?>) type;
    }
    if (type instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType) type;

      // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
      // suspects some pathological case related to nested classes exists.
      Type rawType = parameterizedType.getRawType();
      if (!(rawType instanceof Class)) throw new IllegalArgumentException();
      return (Class<?>) rawType;
    }
    if (type instanceof GenericArrayType) {
      Type componentType = ((GenericArrayType) type).getGenericComponentType();
      return Array.newInstance(getRawType(componentType), 0).getClass();
    }
    if (type instanceof TypeVariable) {
      // We could use the variable's bounds, but that won't work if there are multiple. Having a raw
      // type that's more general than necessary is okay.
      return Object.class;
    }
    if (type instanceof WildcardType) {
      return getRawType(((WildcardType) type).getUpperBounds()[0]);
    }

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

ParameterizedType 表示参数化类型,也就是泛型,如 Collection<String>。
如:

ParameterizedType 接口提供了三个方法:

前两个方法比较常见,以Map<String, Person> map为例,getActualTypeArguments()获取的是String和Person类型的集合。getRawType()是获取到Map类型。

public class ParameterizedTest<T> {
    
    // map对象
    public Map<T,Integer> map;

    public static void main(String[] args) throws Exception{
        
        // 通过反射解析map对象
        Field field = ParameterizedTest.class.getDeclaredField("map");
        Type type =field.getGenericType();
        // 是ParameterizedType类型
        if (type instanceof ParameterizedType) {
            // 1
            Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
            for (Type t : typeArguments) {
                // 参数是TypeVariable
                if (t instanceof TypeVariable) { // T 是 TypeVariable类型
                    System.out.println("TypeVariable: "+((TypeVariable) t).getName());
                } else if (t instanceof Class<?>) { // Integer是Class<?> 原始类型
                    System.out.println("Class<?>: "+t);
                }
            }
            
            // 2、
            Type rawType = ((ParameterizedType) type).getRawType();
            System.out.println("ParameterizedType: "+rawType);
        }
    }
}
结果:
TypeVariable: T
Class<?>: class java.lang.Integer
ParameterizedType: interface java.util.Map
(3)、TypeVariable接口

类型变量,例如:T、K、V等变量。TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型。
接口方法:

public class TypeVariableTest<T> {

    public static void main(String[] args) {
        // 得到T
        TypeVariable<?>[] typeParameters = TypeVariableTest.class.getTypeParameters();
        for (TypeVariable type : typeParameters) {
            System.out.println(type.getGenericDeclaration());  // 查看是哪里申明的
            System.out.println(type.getName());
            System.out.println();
            
            Type[] boundTypes = type.getBounds();
            for (Type boundType : boundTypes) {
                System.out.println(boundType);
            }
        }
    }
}
结果:
class JavaFinal.TypeVariableTest
T

class java.lang.Object

从D getGenericDeclaration()来看,可以在哪些地方声明泛型T了?
需要了解到GenericDeclaration这个接口,这是个声明泛型的接口


GenericDeclaration继承关系

由结构可以看出,一共有三个地方可以声明泛型。

(4)、GenericArrayType接口

泛型数组。 它的组成元素是ParameterizedType或TypeVariable 类型。
接口方法:

下列是几个GenericArrayType泛型例子:

// 属于 GenericArrayType
List<String>[] pTypeArray;
// 属于 GenericArrayType
T[] vTypeArray;
// 不属于 GenericArrayType
List<String> list;
// 不属于 GenericArrayType
String[] strings;
// 不属于 GenericArrayType
Person[] ints;

Retrofit中的例子:

    if (type instanceof GenericArrayType) {
      Type componentType = ((GenericArrayType) type).getGenericComponentType();
      return Array.newInstance(getRawType(componentType), 0).getClass();
    }
(5)、WildcardType

通配符泛型。这个一般不太常使用。只是获取通配符的上限泛型处理。

    if (type instanceof WildcardType) {
      return getRawType(((WildcardType) type).getUpperBounds()[0]);
    }
上一篇 下一篇

猜你喜欢

热点阅读