Java如何获取泛型类型

news/2024/5/19 6:19:14 标签: 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的几个接口子类讲解


http://www.niftyadmin.cn/n/5204481.html

相关文章

2020年下半年试题一:论信息系统项目的成本管理

论文题目 1.概要叙述你参与过的信息系统项目&#xff08;项目的背景、项目规模、发起单位、目的、项目内容、组织结构、项目周期、交付的成果等&#xff09;&#xff0c;并说明你在其中承担的工作&#xff08;项目背景要求本人真实经历&#xff0c;不得抄袭及杜撰&#xff09;。…

Linux 进程等待

在2号手册里查wait&#xff08;&#xff09;。wait()等待任意一个子进程的状态。 wait&#xff08;&#xff09;等待成功会返回该子进程的id,返回失败会返回-1&#xff1a; 小实验 子进程的退出码 子进程执行work()&#xff0c;父进程wait子进程。 子进程跑完5秒之后就e…

Unity开发之C#基础-File文件读取

前言 今天我们将要讲解到c#中 对于文件的读写是怎样的 那么没接触过特别系统编程小伙伴们应该会有一个疑问 这跟文件有什么关系呢&#xff1f; 我们这样来理解 首先 大家对电脑或多或少都应该有不少的了解吧 那么我们这些软件 都是通过变成一个一个文件保存在电脑中 我们才可以…

【大数据Hive】hive 优化策略之job任务优化

目录 一、前言 二、hive执行计划 2.1 hive explain简介 2.1.1 语法格式 2.1.2 查询计划阶段说明 2.2 操作演示 2.2.1 不加条件的查询计划分析 2.2.2 带条件的查询计划分析 三、MapReduce属性优化 3.1 本地模式 3.1.1 本地模式参数设置 3.1.2 本地模式操作演示 3.2 …

【python基础(三)】操作列表:for循环、正确缩进、切片的使用、元组

文章目录 一. 遍历整个列表1. 在for循环中执行更多操作2. 在for循环结束后执行一些操作 二. 避免缩进错误三. 创建数值列表1. 使用函数range()2. 使用range()创建数字列表3. 指定步长。4. 对数字列表执行简单的统计计算5. 列表解析 五. 使用列表的一部分-切片1. 切片2. 遍历切片…

MySQL 事务的底层原理和 MVCC(二)

7.2. undo 日志 7.2.1. 事务回滚的需求 我们说过事务需要保证原子性&#xff0c;也就是事务中的操作要么全部完成&#xff0c;要么什么也不做。但是偏偏有时候事务执行到一半会出现一些情况&#xff0c;比如&#xff1a; 情况一&#xff1a;事务执行过程中可能遇到各种错误&a…

【LeetCode刷题】--43.字符串相乘

43.字符串相乘 方法一&#xff1a;做加法&#xff0c;模拟竖式乘法的方法计算乘积 class Solution {public String multiply(String num1, String num2) {if(num1.equals("0") || num2.equals("0")){return "0";}String res "0";//nu…

移动机器人,开启智能柔性制造新篇章

智能制造是当今工业发展的必然趋势&#xff0c;而柔性制造则是智能制造的重要组成部分。在这个快速变革的时代&#xff0c;如何提高生产效率、降低成本、增强灵活性成为了制造业的关键挑战。富唯智能移动机器人应运而生&#xff0c;为柔性制造注入了新的活力。 基于富唯智能AI-…