`
zzc1684
  • 浏览: 1229232 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Spring4新特性——更好的Java泛型操作API

阅读更多

随着泛型用的越来越多,获取泛型实际类型信息的需求也会出现,如果用原生API,需要很多步操作才能获取到泛型,比如:

Java代码  收藏代码
  1. ParameterizedType parameterizedType =   
  2.     (ParameterizedType) ABService.class.getGenericInterfaces()[0];  
  3. Type genericType = parameterizedType.getActualTypeArguments()[1];  

 

Spring提供的ResolvableType API,提供了更加简单易用的泛型操作支持,如:

Java代码  收藏代码
  1. ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);  
  2. resolvableType1.as(Service.class).getGeneric(1).resolve()  

对于获取更复杂的泛型操作ResolvableType更加简单。

 

假设我们的API是:

Java代码  收藏代码
  1. public interface Service<N, M> {  
  2. }  
  3.   
  4. @org.springframework.stereotype.Service  
  5. public class ABService implements Service<A, B> {  
  6. }  
  7.   
  8. @org.springframework.stereotype.Service  
  9. public class CDService implements Service<C, D> {  
  10. }  

如上泛型类非常简单。 

 

1、得到类型的泛型信息

Java代码  收藏代码
  1. ResolvableType resolvableType1 = ResolvableType.forClass(ABService.class);  

通过如上API,可以得到类型的ResolvableType,如果类型被Spring AOP进行了CGLIB代理,请使用ClassUtils.getUserClass(ABService.class)得到原始类型。

 

可以通过如下得到泛型参数的第1个位置(从0开始)的类型信息

Java代码  收藏代码
  1. resolvableType1.getInterfaces()[0].getGeneric(1).resolve()  

因为我们泛型信息放在 Service<A, B> 上,所以需要resolvableType1.getInterfaces()[0]得到;

 

通过getGeneric(泛型参数索引)得到某个位置的泛型;

resolve()把实际泛型参数解析出来

 

2、得到字段级别的泛型信息

假设我们的字段如下:

Java代码  收藏代码
  1. @Autowired  
  2.  private Service<A, B> abService;  
  3.  @Autowired  
  4.  private Service<C, D> cdService;  
  5.   
  6.  private List<List<String>> list;  
  7.   
  8.  private Map<String, Map<String, Integer>> map;  
  9.   
  10.  private List<String>[] array;  

 

通过如下API可以得到字段级别的ResolvableType

Java代码  收藏代码
  1. ResolvableType resolvableType2 =  
  2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class"cdService"));  

 

然后通过如下API得到Service<C, D>的第0个位置上的泛型实参类型,即C

Java代码  收藏代码
  1. resolvableType2.getGeneric(0).resolve()  

 

比如 List<List<String>> list;是一种嵌套的泛型用例,我们可以通过如下操作获取String类型:

Java代码  收藏代码
  1. ResolvableType resolvableType3 =  
  2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class"list"));  
  3. resolvableType3.getGeneric(0).getGeneric(0).resolve();  

 

更简单的写法

Java代码  收藏代码
  1. resolvableType3.getGeneric(00).resolve(); //List<List<String>> 即String   

 

比如Map<String, Map<String, Integer>> map;我们想得到Integer,可以使用:

Java代码  收藏代码
  1. ResolvableType resolvableType4 =  
  2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class"map"));  
  3. resolvableType4.getGeneric(1).getGeneric(1).resolve();  

更简单的写法  

Java代码  收藏代码
  1. resolvableType4.getGeneric(11).resolve()  

 

3、得到方法返回值的泛型信息

假设我们的方法如下:

Java代码  收藏代码
  1. private HashMap<String, List<String>> method() {  
  2.     return null;  
  3. }  

 

得到Map中的List中的String泛型实参:

Java代码  收藏代码
  1. ResolvableType resolvableType5 =  
  2.                 ResolvableType.forMethodReturnType(ReflectionUtils.findMethod(GenricInjectTest.class"method"));  
  3. resolvableType5.getGeneric(10).resolve();  

 

4、得到构造器参数的泛型信息

假设我们的构造器如下:

Java代码  收藏代码
  1. public Const(List<List<String>> list, Map<String, Map<String, Integer>> map) {  
  2. }  

我们可以通过如下方式得到第1个参数( Map<String, Map<String, Integer>>)中的Integer:

Java代码  收藏代码
  1. ResolvableType resolvableType6 =  
  2.                 ResolvableType.forConstructorParameter(ClassUtils.getConstructorIfAvailable(Const.class, List.class, Map.class), 1);  
  3. resolvableType6.getGeneric(10).resolve();  

 

5、得到数组组件类型的泛型信息

如对于private List<String>[] array; 可以通过如下方式获取List的泛型实参String:

Java代码  收藏代码
  1. ResolvableType resolvableType7 =  
  2.                 ResolvableType.forField(ReflectionUtils.findField(GenricInjectTest.class"array"));  
  3. resolvableType7.isArray();//判断是否是数组  
  4. resolvableType7.getComponentType().getGeneric(0).resolve();  

 

6、自定义泛型类型

Java代码  收藏代码
  1. ResolvableType resolvableType8 = ResolvableType.forClassWithGenerics(List.class, String.class);  
  2.         ResolvableType resolvableType9 = ResolvableType.forArrayComponent(resolvableType8);  
  3. resolvableType9.getComponentType().getGeneric(0).resolve();  

ResolvableType.forClassWithGenerics(List.class, String.class)相当于创建一个List<String>类型;

ResolvableType.forArrayComponent(resolvableType8);:相当于创建一个List<String>[]数组;

resolvableType9.getComponentType().getGeneric(0).resolve():得到相应的泛型信息;

 

7、泛型等价比较:

Java代码  收藏代码
  1. resolvableType7.isAssignableFrom(resolvableType9)  

 

如下创建一个List<Integer>[]数组,与之前的List<String>[]数组比较,将返回false。

Java代码  收藏代码
  1. ResolvableType resolvableType10 = ResolvableType.forClassWithGenerics(List.class, Integer.class);  
  2. ResolvableType resolvableType11= ResolvableType.forArrayComponent(resolvableType10);  
  3. resolvableType11.getComponentType().getGeneric(0).resolve();  
  4. resolvableType7.isAssignableFrom(resolvableType11);  

 

从如上操作可以看出其泛型操作功能十分完善,尤其在嵌套的泛型信息获取上相当简洁。目前整个Spring4环境都使用这个API来操作泛型信息。

 

如之前说的泛型注入:Spring4新特性——泛型限定式依赖注入,通过在依赖注入时使用如下类实现:

GenericTypeAwareAutowireCandidateResolver

QualifierAnnotationAutowireCandidateResolver

ContextAnnotationAutowireCandidateResolver

 

还有如Spring的核心BeanWrapperImpl,以及整个Spring/SpringWevMVC的泛型操作都是替换为这个API 了:GenericCollectionTypeResolver和GenericTypeResolver都直接委托给ResolvableType这 个API。

 

所以大家以后对泛型操作可以全部使用这个API了,非常好用。测试用例请参考GenricInjectTest.java

分享到:
评论

相关推荐

    Spring4新特性(6)更好的Java泛型操作APIJa

    在Spring4框架中,开发者们迎来了一项重要的更新——更优的Java泛型操作API。这一新特性极大地提升了代码的可读性和可维护性,同时也为开发者提供了更强大的工具来处理泛型类型。本文将深入探讨Spring4在这个领域所...

    SSH泛型代码实例

    SSH泛型代码实例是关于Java编程中的一种常见技术——Spring、Struts和Hibernate(SSH)框架结合使用泛型的应用示例。泛型是Java SE 5.0引入的一个重要特性,它允许在编译时检查类型安全,并且所有的强制转换都是自动...

    java爱好者的好帮手——java类库

    学习和熟练运用这些Java类库,不仅能够提升编程效率,还能帮助开发者更好地理解和应用Java的特性。对于初学者,可以通过阅读API文档、实践项目和参考书籍来逐步掌握这些知识。同时,不断更新的Java版本会引入新的...

    spring-framework-reference 3.0

    Spring 3.0 针对Java 5做了全面的升级,这意味着它充分利用了Java 5中的新特性,如泛型、枚举类型等。这些新特性不仅提高了代码的可读性和可维护性,还增加了编译时的安全检查。 ##### 5. Java 基于元数据的配置 ...

    Java学习材料(499篇文章)——Java学习材料(499篇文章)

    10. **泛型**: 泛型增强了代码的类型安全性,允许在编译时检查类型,并提供了更好的代码重用。 11. **注解(Annotation)**: 注解提供了一种向编译器或JVM提供元数据的方式,常用于配置框架(如Spring)或实现元编程...

    java知识精讲+500+面试题.zip

    15. **Java 8及以后的新特性**:如Lambda表达式、Stream API、Optional类等,这些新特性极大地提高了Java的编程效率。 以上只是Java知识体系的一小部分,实际的面试可能会涉及到更多细节,如JDK源码分析、性能调优...

    spring技术文档

    Spring 2.0提供了一系列更新的示例应用程序,帮助开发者更好地理解新特性的使用方法。 **2.9 文档改进** Spring 2.0的官方文档得到了大幅改进,提供了更加详尽的指南和教程,以帮助开发者快速上手。 #### 三、...

    java精华(水木清华站)

    14. **Java 8及以后的新特性**:Java 8引入了Lambda表达式、函数式接口、Stream API等新特性,提高了代码简洁性和效率;Java 11及更高版本也有新的改进和增强。 "Java精华(水木清华站)"可能涵盖以上部分或全部内容...

    java经典问题.rar

    Java编程语言自1995年发布以来,一直以其跨平台、面向对象和安全性等特点深受开发者喜爱。在Java的学习和实践中,经常会遇到一些经典问题,这些问题不仅有助于...通过深入学习和实践,可以更好地掌握Java编程的精髓。

    2021 Java学习路线,已助我成功拿到offer(csdn)————程序.pdf

    最后,为了更好地准备面试和提升学习效率,可以参考作者提到的免费分享的Java学习路线文档,涵盖相关知识点的题目和解答。通过系统的学习和实践,你将能更全面地掌握Java,增加自己在竞争激烈的就业市场中的优势。祝...

    spring's dist.jar

    在Spring 2.5版本中,dist.jar进一步强化了对Java 5特性的支持,如注解(Annotations)、泛型(Generics)等,显著提升了代码的可读性和可维护性。 dist.jar包含的主要模块有: 1. **IoC容器**:Spring的IoC容器是...

    良葛格Java JDK 5.0学习笔记

    在IO流方面,NIO(New IO)在Java 5.0中被引入,提供了一种基于通道(Channel)和缓冲区(Buffer)的I/O模型,相比于传统的流模型,NIO具有更好的非阻塞和选择器特性,适合处理大量并发连接。 最后,JDK 5.0对日期...

    jdk-8u152-windows-x64

    6. **改进的类型推断**:编译器可以更好地推断泛型的类型,减少了类型声明的需要。 7. **Nashorn JavaScript引擎**:JDK 8包含了Nashorn JavaScript引擎,可以直接在Java应用中执行JavaScript代码。 **安装与配置:...

    200道java程序员面试常问知识点

    4. Java集合框架:对List、Set、Map等集合的实现类及其特性有深入了解,包括它们的数据结构、排序和搜索机制。 5. 并发编程:理解线程的创建和运行机制、线程安全、同步机制(synchronized、lock)、死锁、线程池的...

    关于j2ee的学习规划。关于学习的流程跟相应推荐的书籍

    此外,还应该了解Java反射机制,并熟悉Java 1.5之后引入的新特性,如泛型等。 #### 二、JAVA网络编程 在掌握了Java语言基础后,接下来可以进一步学习Java在网络编程方面的应用,这包括但不限于以下内容: - **...

    jdk-8u66-linux-x64源代码

    在Java中,包(package)是一种组织类和接口的方式,帮助避免命名冲突并提供更好的代码管理。 1. **javax**: 这个包通常包含Java扩展框架的一部分,其中包含了标准Java库没有提供的额外功能,如JavaBeans、Java...

    jackson-mapper-asl-1.9.12.jar

    另外,Jackson库本身也在不断更新和发展,新版本引入了更多优化和特性,例如支持JSON-P(JSR 353)和JSON-B(JSR 367),以及对Java 8新特性的支持。 综上所述,`jackson-mapper-asl-1.9.12.jar`是Java开发中处理...

    SCJP详细大纲 多线程

    根据提供的文件信息,我们可以将SCJP(Sun Certified Java Programmer)的大纲内容进行详细的解析与扩展。...以上内容是根据SCJP大纲整理的详细知识点概述,希望能够帮助学习者更好地理解和掌握Java的核心概念与技术。

    j2ee学习路径 对初学者很有帮助

    1. **J2SE基础**:首先,你需要掌握Java的基础,包括面向对象编程的三大特性——封装、继承和多态。理解内存分析、递归、集合类(如ArrayList、HashMap)、泛型、自动装箱与拆箱以及注解(Annotation)。此外,还...

Global site tag (gtag.js) - Google Analytics