Spring泛型处理源码详解,Java泛型处理
创始人
2024-05-20 03:18:26
0

文章目录

  • 一、Java 泛型基础
    • 1、泛型类型擦写
      • 代码实例
    • 2、Java 5 类型接口
      • 源码分析
      • 代码实例
    • 3、更多java泛型相关基础
  • 二、Spring旧版本泛型处理
    • 1、Spring 泛型类型辅助类
      • 代码实例
    • 2、Spring 泛型集合类型辅助类
      • 代码实例
    • 3、Spring 方法参数封装
  • 三、Spring 4.0泛型优化实现
    • 1、ResolvableType
      • 源码分析
      • 代码实例
    • 2、ResolvableType 的局限性
    • 3、ResolvableType 的设计优势
  • 参考资料

一、Java 泛型基础

泛型类型:泛型类型是在类型上参数化的泛型类或接口。

泛型使用场景:
• 编译时强类型检查
• 避免类型强转
• 实现通用算法

1、泛型类型擦写

泛型被引入到 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不会关心泛型的类型。

2、Java 5 类型接口

Java 5 类型接口 - java.lang.reflect.Type:

派生类或接口说明
java.lang.ClassJava 类 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反射获取泛型此处只做简单实例。

3、更多java泛型相关基础

更多java泛型相关基础请自行学习,本文主要介绍Spring对泛型的处理。

二、Spring旧版本泛型处理

1、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 是 List 泛型参数类型的具体化displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, List.class, "getList");// StringList 也是 List 泛型参数类型的具体化displayReturnTypeGenericInfo(GenericTypeResolverDemo.class, List.class, "getStringList");// 泛型参数类型的具体化 具备 ParameterizedType 返回,否则 null// TypeVariableMap typeVariableMap = GenericTypeResolver.getTypeVariableMap(StringList.class);// {E=class java.lang.String, E=class java.lang.String, T=class java.lang.String, E=class java.lang.String, E=class java.lang.String, E=class java.lang.String}// StringList 继承父类包括父接口列表,所以会有多个 E,并且同时指向了 java.lang.String 类对象// typeVariableTypeMap  包含了所有接口中的 TypeVariable 和 Type 的映射,简单地说,E 和 T 这类的,代表泛型参数,Type 代表具体的类型。System.out.println(typeVariableMap);}public static StringList getStringList() {return null;}public static ArrayList getList() { // 泛型参数类型具体化return null;}public static String getString() {return null;}/**** @param containingClass Class类型* @param genericIfc 泛型接口类型* @param methodName 方法名* @param argumentTypes 方法参数* @throws NoSuchMethodException*/private static void displayReturnTypeGenericInfo(Class containingClass, Class genericIfc, String methodName, Class... argumentTypes) throws NoSuchMethodException {// 根据方法名获取MethodMethod method = containingClass.getMethod(methodName, argumentTypes);// 声明类 GenericTypeResolverDemo.class 获取返回值类型Class returnType = GenericTypeResolver.resolveReturnType(method, containingClass);// 常规类作为方法返回值System.out.printf("GenericTypeResolver.resolveReturnType(%s,%s) = %s\n", methodName, containingClass.getSimpleName(), returnType);// 常规类型不具备泛型参数类型 List 获取返回值类型的泛型Class returnTypeArgument = GenericTypeResolver.resolveReturnTypeArgument(method, genericIfc);System.out.printf("GenericTypeResolver.resolveReturnTypeArgument(%s,%s) = %s\n", methodName, containingClass.getSimpleName(), returnTypeArgument);}}class StringList extends ArrayList { // 泛型参数具体化(字节码有记录)
}
 

2、Spring 泛型集合类型辅助类

核心 API - org.springframework.core.GenericCollectionTypeResolver

版本支持:[2.0 , 4.3] (新版本的spring已经不用了)

替换实现:org.springframework.core.ResolvableType

处理 Collection 相关
• getCollection*Type

处理 Map 相关
• getMapKeyType
• getMapValue
Type

代码实例


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

3、Spring 方法参数封装

核心 API - org.springframework.core.MethodParameter

起始版本:[2.0 , )

元信息(部分)
• 关联的方法 - Method
• 关联的构造器 - Constructor
• 构造器或方法参数索引 - parameterIndex
• 构造器或方法参数类型 - parameterType
• 构造器或方法参数泛型类型 - genericParameterType
• 构造器或方法参数参数名称 - parameterName
• 所在的类 - containingClass

三、Spring 4.0泛型优化实现

1、ResolvableType

核心 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 {
}

2、ResolvableType 的局限性

局限一:ResolvableType 无法处理泛型擦写

局限二:ResolvableType 无法处理非具体化的 ParameterizedType

3、ResolvableType 的设计优势

简化 Java 5 Type API 开发,屏蔽复杂 API 的运用,如 ParameterizedType

不变性设计(Immutability)

Fluent API 设计(Builder 模式),链式(流式)编程

参考资料

极客时间-《小马哥讲 Spring 核心编程思想》

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...