Java 中的Type类型及其实现【学习记录】

news2024/9/20 19:44:24

概述

在JDK1.5之前只有原始类型,此时所有的原始类型都通过字节码文件类Class进行抽象。Class类的一个具体对象就代表一个指定的原始类型。

JDK1.5加入了泛型类,扩充了数据类型,从只有原始类型基础上扩充了参数化类型、类型变量类型、通配符类型、泛型数组类型。Type是Java语言中所有类型(Class)的公共父接口。

Type类关系图

在这里插入图片描述
从左到右依次是:

  • Class(原始/基本类型):不仅包括我们平常所指的类、枚举、数组、注解,还包括基本类型int、float等等。
  • TypeVariable(类型变量):比如List中的T等。
  • WildcardType(通配符类型):也叫做泛型表达式类型,例如List<? extends Number>这种。
  • ParameterizedType(参数化类型):就是我们平常所用到的泛型List、Map(注意和TypeVariable的区别,参数化类型表示的是List这样的一个整体而不是T)。
  • GenericArrayType(泛型数组类型):并不是我们工作中所使用的数组String[]、Byte[](这些都是Class),而是到带有泛型的数组,即T[]。

Type接口本身算是一个标记接口,不提供任何需要复写的方法。

TypeVariable类型变量

泛型信息在编译时会被转换成一个特定的类型,而TypeVariable就是用来反应JVM编辑该泛型前的信息。(通俗的讲,TypeVariable就是我们常用的List<T>、Map<K,V>中的T,K这种泛型变量)。

还可以对类型变量加上extends限定,这样会有类型变量对应的上限;值的注意的是,类型变量的上限可以有多个,必须使用&连接,例如:List<T extends Number & Serializable>,其中&后必须是接口。

1)TypeVariable源码:

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
 	// 类型变量对应的上边界,如果没有指定上限,返回Object 可以有多个
    Type[] getBounds();
    // 获取类型变量所在类的Type,比如TypeVariableTest<T>类,getGenericDeclaration()得到的就是TypeVariableTest。
    D getGenericDeclaration();
	// 获取类型变量在源码中定义的名称
    String getName();
	// JDK8新增的,获取注解类型的上限数组
     AnnotatedType[] getAnnotatedBounds();
}

2)具体用法:

public class TypeVariableTest<K extends Number, T> {
    // K有指定上边界 Number
    private K key;
    // T没有指定上边界,其默认上边界为Object
    private T value;

    public static void main(String[] args) {
        TypeVariable<Class<TypeVariableTest>>[] typeParameters = TypeVariableTest.class.getTypeParameters();
        for (TypeVariable<Class<TypeVariableTest>> type : typeParameters) {
            int index = type.getBounds().length - 1;
            // 输出上边界
            System.out.println("---getBounds()-- " + type.getBounds()[index]);
            // 输出名称
            System.out.println("---getName()-- " + type.getName());
            // 输出所在的类的类型
            System.out.println("---getGenericDeclaration()-- " + type.getGenericDeclaration());
        }
    }
}

3)输出结果:

---getBounds()-- class java.lang.Number
---getName()-- K
---getGenericDeclaration()-- class com.study.concurrentprogramming.genericiy.TypeVariableTest
---getBounds()-- class java.lang.Object
---getName()-- T
---getGenericDeclaration()-- class com.study.concurrentprogramming.genericiy.TypeVariableTest

WildCardType通配符类型

表示通配符类型,比如<?>,<? extends Number>等

如果没有指定的上边界,则默认Object,如果没有指定下边界,则默认为String。

1)WildCardType源码:

public interface WildcardType extends Type {
 	// 获得泛型表达式上边界,表达式中使用extends
    Type[] getUpperBounds();
 	// 或者泛型表达式的下边界,表达式中使用super
    Type[] getLowerBounds();
}

2)具体用法:

public class WildcardTypeTest {
    // 使用通配符类型参数的方法
    public void testWildcardType(
    	List<? extends OutputStream> outputStreams, 
    	List<? super InputStream> inputStreams,
        List<Integer> list, InputStream inputStream) {
    }

    public static void main(String[] args) {
        // 获取WildcardTypeTest类的所有方法(本例中是testWildcardType方法)
        Method[] declaredMethods = WildcardTypeTest.class.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println("method name: " + method.getName());
            // 获取方法的所有参数类型
            Type[] genericParameterTypes = method.getGenericParameterTypes();
            for (Type type : genericParameterTypes) {
                System.out.println("type: " + type.toString());
                // 如果不是参数化类型则直接continue
                if (!(type instanceof ParameterizedType)) {
                    continue;
                }
                // 将当前类型强转为参数化类型并获取实际参数(即含有通配符的泛型类型)
                Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];
                // 输出其是否为通配符类型
                System.out.println("type instanceof WildcardType: "
                        + (actualTypeArgument instanceof WildcardType));
                if (actualTypeArgument instanceof WildcardType) {
                    int lowIndex = ((WildcardType) actualTypeArgument).getLowerBounds().length - 1;
                    int upperIndex = ((WildcardType) actualTypeArgument).getUpperBounds().length - 1;
                    // 输出上边界与下边界
                    System.out.println("getLowerBounds(): " +
                            (lowIndex >= 0 ? ((WildcardType) actualTypeArgument).getLowerBounds()[lowIndex] : "String")
                            + ";getUpperBounds(): " +
                            (upperIndex >= 0 ? ((WildcardType) actualTypeArgument).getUpperBounds()[upperIndex] : "Object"));
                }
            }
        }
    }
}

3)输出结果:

method name: main
type: class [Ljava.lang.String;
method name: testWildcardType
type: java.util.List<? extends java.io.OutputStream>
type instanceof WildcardType: true
getLowerBounds(): String;getUpperBounds(): class java.io.OutputStream
type: java.util.List<? super java.io.InputStream>
type instanceof WildcardType: true
getLowerBounds(): class java.io.InputStream;getUpperBounds(): class java.lang.Object
type: java.util.List<java.lang.Integer>
type instanceof WildcardType: false
type: class java.io.InputStream

//后面待更新…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenStack使用Skyline Dashboard面板替换默认Horizon面板

书接上回 OpenStack Yoga安装使用kolla-ansible 忘记提示了。如果截止发稿今天&#xff0c;使用最新zed版本&#xff0c;在最后一步部署阶段会报错&#xff0c;好像是rabbitMQ重启失败。所以建议使用最新版再退一个版本 官方文档 skyline-apiserver/README-zh_CN.md at maste…

一文入门图像分类

文章目录一、卷积网络1.1 卷积的参数量1.2 卷积的计算量1.3 降低模型参数量和计算量的方法1.3.1 GoogLeNet 使用不同大小的卷积核1.3.2 ResNet 使用11卷积压缩通道数1.3.3 可分离卷积二、Transformer2.1 注意力机制 Attention Mechanism2.2 多头注意力 Multi-head (Self-)Atten…

基于SSM框架宠物管理系统

一、项目简介 本项目是一套基于ssm框架宠物管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse…

学习笔记:Java 并发编程⑥_线程池

若文章内容或图片失效&#xff0c;请留言反馈。 部分素材来自网络&#xff0c;若不小心影响到您的利益&#xff0c;请联系博主删除。 视频链接&#xff1a;https://www.bilibili.com/video/av81461839配套资料&#xff1a;https://pan.baidu.com/s/1lSDty6-hzCWTXFYuqThRPw&am…

软件测试-移动端测试示例1-笔记

搭建环境移动端测试试验连接真机不方便&#xff0c;在此通过电脑端进行一个测试安装JDK环境参考一下文章https://blog.csdn.net/weixin_47260194/article/details/122595008?spm1001.2014.3001.5502Android SDK环境配置首先去到官网https://www.androiddevtools.cn/下载SDK&am…

【虹科新品】采用NVIDIA Jetson Orin NX系统的视觉边缘计算机

虹科是智能感知与机器视觉领域领先资源整合及技术服务落地供应商&#xff0c;已经和Gidel展开深度的技术合作&#xff0c;为用户提供图像采集卡、FPGA图像处理和高带宽图像采集等服务。目前已经陆续在国内完成了多家一线公司的汽车图像采集、AOI、晶圆半导体检测项目。Gidel推出…

JS 执行上下文和作用域

与JS 中的作用域一同出现的还有一个执行上下文&#xff08;execution context&#xff09;的概念&#xff0c;这两个概念容易混淆&#xff0c;今天就来聊聊他们。 作用域 作用域是指程序源代码中定义变量、函数的区域&#xff0c;它规定了变量和函数可以访问哪些数据以及他们…

C语言和汇编语言混合编程

ATPCS ATPCS的全称是ARM-Thumb Procedure Call Standard&#xff0c;其核心内容就是定义了ARM子程序调用的基本规则及堆栈的使用约定等。如ATPCS规定了ARM程序要使用满递减堆栈&#xff0c;入栈/出栈操作要使用STMFD/LDMFD指令&#xff0c;只要所有的程序都遵循这个约定&#…

前端开发环境部署问题

很多开发者到了一家新公司&#xff0c;公司发了一台新电脑&#xff0c;对环境安装比较困惑。今天带大家还原&#xff0c;拿到公司电脑&#xff0c;如何安装你需要的各种环境。 一、node按装 官网下载地址&#xff1a; http://nodejs.cn/download/ 根据自己需要下载对应的版本…

深度 | Web 3.0时代去中心化IM 的挑战与思考

前言 Web3.0时代的重要特点&#xff1a; 1、数据主权 用户将拥有自己的数据主权&#xff0c;用户所创造的数字内容&#xff0c;所有权和控制权都归属于用户&#xff0c;用户所创造的价值可以由用户自主支配。对于IM业务&#xff0c;就是用户的好友列表&#xff0c;聊天消息等…

windowXP系统无法正常访问vue3网页

开发完的vue3项目需要在XP系统环境使用 由于在立项时采用了开发成本较低速度较快的vue3技术栈&#xff0c;并没有考虑到工厂的设备仍然在试用二十年前的机器&#xff0c;导致项目上线后有部分人员打开页面展示白屏。 经过排查&#xff0c;发现由于vue3使用ES6的Proxy代理实现响…

Linux-目录结构及文件基本操作

目录1、Linux目录结构1.1 FHS标准1.2 目录路径2、Linux文件的基本操作2.1 新建2.2 复制2.3 删除2.4 移动文件与文件重命名2.5 查看文件2.6 查看文件类型2.7 编辑文件1、Linux目录结构 Linux的目录结构和Windows的目录结构在实现上是完全不同的 Windows以存储介质为主&#xff…

Vue-Cli 脚手架 搭建 Vue项目

本篇目开始进行Vue基于项目中的介绍&#xff0c;Vue-cli 是官方提高用于搭建基于 Vue、Webpack、ES6 项目目的脚手架工具&#xff0c;可以前往在线官网查看&#xff1a;—— 官方文档 | Vue CLI 。 安装npm 1. 检测是否安装了Node.js &#xff0c;未安装请前往下载&#xff1b;…

【内网安全-隧道搭建】内网穿透_Ngrok上线(美版、国版二开)

目录 一、准备 1、意义&#xff1a; 2、项目&#xff1a; 二、内网穿透 1、简介&#xff1a; 三、Ngrok&#xff08;入门上线&#xff09; 1、简述&#xff1a; 2、Ngrok入门上线&#xff08;国版二开&#xff09; 3、相关工具&#xff1a; 2、Ngrok入门上线&#xff…

低代码开发平台|SRM-招投标管理搭建指南

1、简介1.1、案例简介本文将介绍&#xff0c;如何搭建SRM-招投标管理。1.2、应用场景企业根据采购需求创建招投标需求&#xff0c;选择供应商进行邀标&#xff0c;供应商报名再投标&#xff0c;投标结束评标人员对投标项目进行评估。2、设置方法2.1、表单搭建1&#xff09;新建…

Python build Exe 使用PyInstaller创建可执行的Python脚本

在本指南中&#xff0c;您将看到如何使用PyInstaller创建Python脚本的可执行文件? 下面是在Windows中实现这一目标的完整步骤。 使用PyInstaller创建可执行文件的步骤 步骤1:添加Python到Windows路径 首先&#xff0c;您可能想要将Python添加到Windows路径。 将Python添加到…

Spring Boot整合Redis笔记

文章目录前言Java 操作 RedisJedis 操作-测试Jedis 实例-手机验证码Redis与Spring Boot整合整合步骤Redis 的事务操作Redis的事务定义Multi、Exec、discard 基本命令事务冲突的问题为什么要做成事务悲观锁乐观锁WATCH key [key ... ]Redis事务三特性Redis事务秒杀案例解决计数器…

分布式定时任务-XXL-JOB-教程+实战

一.定时任务概述 1.定时任务认识 1.1.什么是定时任务 定时任务是按照指定时间周期运行任务。使用场景为在某个固定时间点执行&#xff0c;或者周期性的去执行某个任务&#xff0c;比如&#xff1a;每天晚上24点做数据汇总&#xff0c;定时发送短信等。 1.2.常见定时任务方案…

docker-compose容器编排部署

docker-compose部署微服务1、Docker-Compose是什么&#xff1f;2、应用场景3、docker-compose部署SpringBoot项目3.1 编写Dockfile3.2 编写docker-compose.yaml3.3 修改工程配置3.4 将相关文件上传到服务器3.5 执行docker-compose up本文是对DockerNginx打包部署前后端分离项目…

E5061B矢量网络分析仪VNA概念

矢量网络分析仪VNA是一种测试仪器&#xff0c;它可以将网络的响应测量成矢量:实参数和虚参数&#xff0c;从而表征其性能。矢量网络分析仪VNA是射频设计实验室和许多制造和服务领域的重要测试仪器。虽然矢量网络分析仪主要侧重于研究和开发&#xff0c;但它也可以为所有类型的R…