Java如何获取泛型类型

泛型(Generic)

泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Ada、Delphi、Eiffel、Java、C#、F#、Swift 和 Visual Basic .NET 称之为泛型(generics);ML、Scala 和 Haskell 称之为参数多态(parametric polymorphism);C++ 和 D称之为模板。具有广泛影响的1994年版的《Design Patterns》一书称之为参数化类型(parameterized type)。

泛型定义及目的

泛型的定义主要有以下两种:

  1. 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)
  2. 在程序编码中一些包含参数的类。其参数可以代表类或对象等等。(现在人们大多把这称作模板)

不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。

一些强类型程序语言支持泛型,其主要目的是加强类型安全及减少类转换的次数,但一些支持泛型的程序语言只能达到部分目的。

泛型类、泛型接口、泛型方法可参考链接:泛型

如何获取泛型类型

通过反射方式获取

1)通过反射获取父类对象的类型;

2)判断是参数化类型还是Class类型,如果是Class类型则获取父类的父类对象类型;

3)拿到参数化类型,获取该类型中的泛型类型;

ParameterizedType是参数化类型,即带有泛型的类型,比如List<String>、Set<Long>、Map<String, Long>、Class<Float>等类型;

其中它有三个方法

  • getActualTypeArguments():获取该类型中的泛型类型;
  • getRawType():获取对应的原始类型,比如List<String>类型的原始类型就是List
  • getOwnerType():获取拥有者的类型,当该类型是内部类的时候,获取外层类的类型,如果不是内部类则返回的都是null。
java 复制代码
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class AccessGenericTypeDemo {
    static class SuperClass<T> {
    }

    /**
     * 强引用:  当一个对象被强引用变量引用时,它处于可达状态,是不可能被垃圾回收器回收的,即使该对象永远不会被用到也不会被回收。
     * 软引用:  当系统内存充足时它不会被回收,当系统内存不足时它才会被回收。
     * 弱引用:  只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,都会回收该对象占用的内存。
     * 虚引用:  在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(RefenenceQueue)联合使用。
     */
    private static class Clazz extends SuperClass<ReferenceQueue> {
    }

    /**
     * 通过反射方式获取父类泛型类型
     */
    private static Type getSuperClassGenericType() {
        // 获取当前对象的直接父类的类型
        Type type = Clazz.class.getGenericSuperclass();
        // ParameterizedType获取 参数化类型 ,即平常所用到的泛型List<String>、Map<K,V>,Set<T>,Class<?> 数组类型(GenericArrayType)
        if (type instanceof ParameterizedType) {
            return ((ParameterizedType) type).getActualTypeArguments()[0];
            // 两层继承
        } else if (type instanceof Class) {
            type = ((Class<?>) type).getGenericSuperclass();
            return ((ParameterizedType) type).getActualTypeArguments()[0];
        } else {
            throw new ClassCastException("get class error,actual type is " + Clazz.class.getCanonicalName());
        }
    }

    public static void main(String[] args) {
        System.out.println(getSuperClassGenericType());
    }
}

通过Spring框架的ResolvableType获取

官方文档链接:docs.spring.io ------ ResolvableType

java 复制代码
import org.springframework.core.ResolvableType;

import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Type;

public class AccessGenericTypeDemo {
    static class SuperClass<T> {
    }
    
    private static class Clazz extends SuperClass<ReferenceQueue> {
    }

    /**
     * 通过 org.springframework.core.ResolvableType 获取父类对象
     *
     * @return ResolvableType
     */
    private static Type getResolvableType() {
        return ResolvableType.forClass(Clazz.class).getSuperType().getGeneric(0).resolve();
    }

    public static void main(String[] args) {
        System.out.println(getResolvableType());
    }
}

两者获取结果如下,

扩展

上面Type类型的子类除了Class和ParameterizedType,还有GenericArrayType、TypeVariable、WildcardType,可参考:简书_Type的几个接口子类讲解

相关推荐
快乐就好ya1 小时前
Java多线程
java·开发语言
IT学长编程1 小时前
计算机毕业设计 二手图书交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·二手图书交易系统
CS_GaoMing2 小时前
Centos7 JDK 多版本管理与 Maven 构建问题和注意!
java·开发语言·maven·centos7·java多版本
艾伦~耶格尔2 小时前
Spring Boot 三层架构开发模式入门
java·spring boot·后端·架构·三层架构
man20172 小时前
基于spring boot的篮球论坛系统
java·spring boot·后端
2401_858120533 小时前
Spring Boot框架下的大学生就业招聘平台
java·开发语言
S hh3 小时前
【Linux】进程地址空间
java·linux·运维·服务器·学习
Java探秘者3 小时前
Maven下载、安装与环境配置详解:从零开始搭建高效Java开发环境
java·开发语言·数据库·spring boot·spring cloud·maven·idea
攸攸太上3 小时前
Spring Gateway学习
java·后端·学习·spring·微服务·gateway
2301_786964363 小时前
3、练习常用的HBase Shell命令+HBase 常用的Java API 及应用实例
java·大数据·数据库·分布式·hbase