本篇内容主要讲解“Java泛型的概念和Type类型体系”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java泛型的概念和Type类型体系”吧!
1 JAVA的Type类型体系
先了解下java的Type类型体系(类的类=>类型),Type是所有类型(原生类型-Class、参数化类型-Parameterizedtype、数组类型-GenericArrayType、类型变量-TypeVariable、基本类型-Class)的共同接口;前两篇反射和注解讲到的Class就是Type的一实现类

Type下面又有四个子接口类ParameterizedType、TypeVariable、GenericArrayType、WildcardType
注解是JDK1.5才出现了的,为了表示被注解的类型的,加入AnnotatedElement类型,字面意思就是被注解的元素。JDK1.8又有了AnnotatedType将Type和被注解元素的概念关联起来。

AnnotatedType也有四个子接口,和Type的四个子接口一一对应,如:ParameterizedType类型被注解则被编译器解析成AnnotatedParameterizedType: @AnTest("list")List
list
2 泛型的概念
泛型: 把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型
3 泛型类和泛型方法的示例
public class MainTest<T> { private T param; } public static void main(String[] args){ MainTest<String> data = new MainTest<String>(){}; ParameterizedType genType1 = (ParameterizedType)data.getClass().getGenericSuperclass(); }public class MainTest{ public static void main(String[] args){ printData("siting"); } static <T> T printData(T t){ System.out.println(t); return t; } }接口和抽象类都可以使用泛型
4 类型擦除
public class MainTest { public static void main(String[] args){ List<String> strArr = new ArrayList<>(); List<Integer> intArr = new ArrayList<>(); Type strClazz = strArr.getClass(); Type intClazz = intArr.getClass(); } }
public class MainTest<T> { T param; public static void main(String[] args){ MainTest<String> test = new MainTest<>(); test.setParam("siting"); } public T getParam() { return param; } public void setParam(T param) { this.param = param; } } public class com/MainTest { ...省略 public static main([Ljava/lang/String;)V L0 LINENUMBER 7 L0 NEW com/MainTest DUP INVOKESPECIAL com/MainTest.<init> ()V ASTORE 1 L1 LINENUMBER 8 L1 ALOAD 1 LDC "siting" // 调用类型擦除后的setParam(Object) INVOKEVIRTUAL com/MainTest.setParam (Ljava/lang/Object;)V L2 ...省略//getParam 的返回值是Object public getParam()Ljava/lang/Object; L0 LINENUMBER 10 L0 ALOAD 0 GETFIELD com/MainTest.param : Ljava/lang/Object; ARETURN ...省略//setParam 的入参是Object public setParam(Ljava/lang/Object;)V L0 LINENUMBER 11 L0 ALOAD 0 ALOAD 1 PUTFIELD com/MainTest.param : Ljava/lang/Object; RETURN ... }可以看出T(String)都被转换为Object类型,最初的初始化的String不见了
5 泛型的继承
public class MainTest<T> { T param; static public class SubTest1 extends MainTest<String>{} static public class SubTest2<R> extends MainTest<R>{} //SubTest3继承的时原生类型 static public class SubTest3 extends MainTest{} }
6 泛型变量TypeVariable
(先临时定义一个名称,Test
里的E为泛型参数);泛型变量TypeVariable:泛型的泛型参数就是TypeVariable;当父类使用子类的泛型参数指定自身的泛型参数时;或者泛型属性定义在泛型类A中,并使用泛型类A的泛型参数T时,其泛型参数都会被编译器定为泛型变量TypeVariable,而不是被擦除
public class MainTest<T> { List<T> param; public static void main(String[] args) throws Exception{ Class clazz = MainTest.class; TypeVariable[] typeVariable = clazz.getTypeParameters(); // 1 Field field = clazz.getDeclaredField("param"); ParameterizedType arrayType = (ParameterizedType)field.getGenericType(); // interface List<E> 的泛型类型E被T,具体化,因此其被识别为 TypeVariable TypeVariable variable1 = (TypeVariable)arrayType.getActualTypeArguments()[0]; // 2 ParameterizedType type = (ParameterizedType)SubTest.class.getGenericSuperclass(); TypeVariable variable2 = (TypeVariable)type.getActualTypeArguments()[0]; } static class SubTest<R> extends MainTest<R>{} }7 参数化类型ParameterizedType
public interface ParameterizedType extends Type { //获取实际参数,List<String>里的String; 如果是List<T>则是TypeVariable类型 Type[] getActualTypeArguments(); // 获取原始类型List<String> -> List<E> Type getRawType(); Type getOwnerType(); }public class MainTest<T> { public static void main(String[] args){ MainTest<String> str = new MainTest<String>(); Class variable = str.getClass(); Type genType1 = variable.getGenericSuperclass(); } }
// 1 子类继承泛型时,指定具体参数(可以是String等已知类型,也可以是子类的泛型参数) // 2 获取在类内部定义的泛型属性,需指定具体泛型参数 // 3 局部代码,可以通过泛型的匿名内部子类(需指定具体泛型参数)获取ParameterizedType类型 public class MainTest<T> { List<T> list; public static void main(String[] args) throws NoSuchFieldException { SubTest<String> str = new SubTest<>(); // 方式一 Class variable = str.getClass(); // 父类是(521)ParameterizedType类型 ParameterizedType genType = (ParameterizedType)variable.getGenericSuperclass(); // (521)ParameterizedType类型的原生类型是(479)class com.MainTest Type clazz = genType.getRawType(); //MainTest.class 的原生类型是 (479)class com.MainTest Class rawClazz = MainTest.class; //方式二,泛型属性 Field field = rawClazz.getDeclaredField("list"); //属性list 类型是(546)ParameterizedType类型List<T> ParameterizedType fieldType = (ParameterizedType)field.getGenericType(); // 方式三 MainTest<String> sub3 = new MainTest<String>(){}; // clazz3是匿名子类 Class clazz3 = sub3.getClass(); //父类是(555)ParameterizedType类型 ParameterizedType genType3 = (ParameterizedType) clazz3.getGenericSuperclass(); // (555)ParameterizedType类型的原生类型是(479)class com.MainTest Type type3 = genType3.getRawType(); } public static class SubTest<R> extends MainTest<R>{ } }
8 通配符(WildcardType)
无边界通配符:无界通配符 ? 可以适配任何引用类型:
public static void print(List list){} ----->>> public static void print(List<?> list){}
上界限定通配符 < ? extends E>
public static void print(List<? extends Number> list) { Number n = new Double("1.0"); list.add(n); Number tmp = list.get(0); }
下界限定通配符 < ? super E>
class Parent{ } class Child extends Parent{ } public class MainTest<T> { T param; public static void main(String[] args){ MainTest<? super Child> parent_m = new MainTest<>(); parent_m.setParam(new Child()); Object parent = parent_m.getParam(); } public T getParam() { return param; } public void setParam(T param) { this.param = param; } }
9 泛型数组(GenericArrayType)
public interface GenericArrayType extends Type { //获得这个数组元素类型,即获得:A<T>(A<T>[])或 T(T[]) Type getGenericComponentType(); }public class MainTest<T> { T[] param; public static void main(String[] args) throws Exception{ Class clazz = MainTest.class; Field field = clazz.getDeclaredField("param"); GenericArrayType arrayType = (GenericArrayType)field.getGenericType(); TypeVariable variable = (TypeVariable) arrayType.getGenericComponentType(); } }
到此,相信大家对“Java泛型的概念和Type类型体系”有了更深的了解,不妨来实际操作一番吧!这里是天达云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!