泛型类型:泛型类型是在类型上参数化的泛型类或接口。
泛型使用场景:
• 编译时强类型检查
• 避免类型强转
• 实现通用算法
泛型被引入到 Java 语言中,以便在编译时提供更严格的类型检查并支持泛型编程。类型擦除确保不会为参数化类型创建新类;因此,泛型不会产生运行时开销。为了实现泛型,编译器将类型擦除应用于:
• 将泛型类型中的所有类型参数替换为其边界,如果类型参数是无边界的,则将其替换为“Object”。因此,生成的字节码只包含普通类、接口和方法
• 必要时插入类型转换以保持类型安全
• 生成桥方法以保留扩展泛型类型中的多态性
List list = new ArrayList<>();
list.add("hello");
list.add("world");// 1.将有泛型约束的list赋值给没有泛型约束的一个新集合
List temp = list;// 2.此时temp可以添加任意对象到集合中
temp.add(2);// 3.使用temp获取集合中的元素可以正常获取,没有泛型约束意味着参数类型无边界
// 则将其泛型替换为Object类型
System.out.println(temp.get(2));// 4.使用list获取集合中的元素会抛出类型转换异常,因为list集合的泛型为String类型
// 在获取元素时,会进行一次类型转换将元素转为String类型,所以会报错
System.out.println(list.get(2));
Java泛型 更多的是编译期间给我们做的强类型约束,而运行时JVM不会关心泛型的类型。
Java 5 类型接口 - java.lang.reflect.Type:
派生类或接口 | 说明 |
---|---|
java.lang.Class | Java 类 API,如 java.lang.String |
java.lang.reflect.GenericArrayType | 泛型数组类型 |
java.lang.reflect.ParameterizedType | 泛型参数类型 |
java.lang.reflect.TypeVariable | 泛型类型变量,如 Collection 中的 E |
java.lang.reflect.WildcardType | 泛型通配类型 |
Java 泛型反射 API:
类型 | API |
---|---|
泛型信息(Generics Info) | java.lang.Class#getGenericInfo() |
泛型参数(Parameters) | java.lang.reflect.ParameterizedType |
泛型父类(Super Classes) | java.lang.Class#getGenericSuperclass() |
泛型接口(Interfaces) | java.lang.Class#getGenericInterfaces() |
泛型声明(Generics Declaration) | java.lang.reflect.GenericDeclaration |
我们看一下Class类,实现了Type接口。
public final class Class implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement {
Type接口在JDK1.8之前,是一个空的接口,表示Java编程语言中所有类型的公共超接口。这些类型包括原始类型、参数化类型、数组类型、类型变量和基本类型。1.8之后增加了一个方法:
public interface Type {default String getTypeName() {return toString();}
}
Class中有着很多对泛型操作的方法,获取的泛型类型就是Type类型。
// 基本类型 primitive types : int long float
Class intClass = int.class;// 数组类型 array types : int[],Object[]
Class objectArrayClass = Object[].class;// 原始类型 raw types : java.lang.String
Class rawClass = String.class;// 泛型参数类型 parameterized type
ParameterizedType parameterizedType = (ParameterizedType) ArrayList.class.getGenericSuperclass();// parameterizedType.getRawType() = java.util.AbstractList// 泛型类型变量 Type Variable:System.out.println(parameterizedType.toString()); // java.util.AbstractList//
Type[] typeVariables = parameterizedType.getActualTypeArguments();Stream.of(typeVariables).map(TypeVariable.class::cast) // Type -> TypeVariable.forEach(System.out::println);
java反射获取泛型此处只做简单实例。
更多java泛型相关基础请自行学习,本文主要介绍Spring对泛型的处理。
核心 API - org.springframework.core.GenericTypeResolver
版本支持:[2.5.2 , )
处理类型相关(Type)相关方法
• resolveReturnType
• resolveType
处理泛型参数类型(ParameterizedType)相关方法
• resolveReturnTypeArgument
• resolveTypeArgument
• resolveTypeArguments
处理泛型类型变量(TypeVariable)相关方法
• getTypeVariableMap
import org.springframework.core.GenericTypeResolver;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;/*** {@link GenericTypeResolver} 示例*/
public class GenericTypeResolverDemo {public static void main(String[] args) throws NoSuchMethodException {// String 是 Comparable 具体化displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, Comparable.class, "getString");// ArrayList
核心 API - org.springframework.core.GenericCollectionTypeResolver
版本支持:[2.0 , 4.3] (新版本的spring已经不用了)
替换实现:org.springframework.core.ResolvableType
处理 Collection 相关
• getCollection*Type
处理 Map 相关
• getMapKeyType
• getMapValueType
import org.springframework.core.GenericCollectionTypeResolver;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;/*** {@link GenericCollectionTypeResolver} 示例*/
public class GenericCollectionTypeResolverDemo {private static StringList stringList;private static List strings;public static void main(String[] args) throws Exception {// StringList extends ArrayList 具体化// getCollectionType 返回具体化泛型参数类型集合的成员类型 = StringSystem.out.println(GenericCollectionTypeResolver.getCollectionType(StringList.class));System.out.println(GenericCollectionTypeResolver.getCollectionType(ArrayList.class));// 获取字段Field field = GenericCollectionTypeResolverDemo.class.getDeclaredField("stringList");System.out.println(GenericCollectionTypeResolver.getCollectionFieldType(field));field = GenericCollectionTypeResolverDemo.class.getDeclaredField("strings");System.out.println(GenericCollectionTypeResolver.getCollectionFieldType(field));}
}
核心 API - org.springframework.core.MethodParameter
起始版本:[2.0 , )
元信息(部分)
• 关联的方法 - Method
• 关联的构造器 - Constructor
• 构造器或方法参数索引 - parameterIndex
• 构造器或方法参数类型 - parameterType
• 构造器或方法参数泛型类型 - genericParameterType
• 构造器或方法参数参数名称 - parameterName
• 所在的类 - containingClass
核心 API - org.springframework.core.ResolvableType
• 起始版本:[4.0 , )
• 扮演角色:GenericTypeResolver 和 GenericCollectionTypeResolver 替代者
• 工厂方法:for* 方法
• 转换方法:as* 方法
• 处理方法:resolve* 方法
ResolvableType封装Java类型,提供对超类型、接口和泛型参数的访问,以及最终解析为类的能力。
Doc中有一个实例:
ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
t.getSuperType(); // AbstractMap>
t.asMap(); // Map>
t.getGeneric(0).resolve(); // Integer
t.getGeneric(1).resolve(); // List
t.getGeneric(1); // List
t.resolveGeneric(1, 0); // String
public class ResolvableTypeDemo {public static void main(String[] args) {// 工厂创建// StringList <- ArrayList <- AbstractList <- List <- CollectionResolvableType resolvableType = ResolvableType.forClass(StringList.class);resolvableType.getSuperType(); // ArrayListresolvableType.getSuperType().getSuperType(); // AbstractListSystem.out.println(resolvableType.asCollection().resolve()); // 获取 Raw Type(interface java.util.Collection)System.out.println(resolvableType.asCollection().resolveGeneric(0)); // 获取泛型参数类型(class java.lang.String)}
}class StringList extends ArrayList {
}
局限一:ResolvableType 无法处理泛型擦写
局限二:ResolvableType 无法处理非具体化的 ParameterizedType
简化 Java 5 Type API 开发,屏蔽复杂 API 的运用,如 ParameterizedType
不变性设计(Immutability)
Fluent API 设计(Builder 模式),链式(流式)编程
极客时间-《小马哥讲 Spring 核心编程思想》
上一篇:【数据结构】详解顺序表