Java Type

news2024/11/15 7:30:37

Type 是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java 中所有类型的”爹“。其中”所有类型“的描述尤为指的关注。它并不是我们平常工作中经常使用的int、String、List、Map等数据类型,而是从Java语言角度磊说,对基本类型、引用类型向上的抽象

Java Type

    • Type 体系中的类型
    • Type 与子类,子接口的关系
      • Class
      • Type
      • ParameterizedType (参数化类型)
      • GenericArrayType (泛型数组类型)
      • TypeVariable (类型变量类型)
        • GenericDeclaration
        • 【extends 和 super的区别】
      • WildcardType (泛型表达式或者通配符表达式)
    • 示例

Type 体系中的类型

Type 体系中类型的包括

  • 原始类型(Class):不仅仅包括我们平常所指的类,还包括枚举、数组、注解等
  • 参数化类型(ParameterizedType):就是我们平常所用到的泛型List、Map
  • 泛型数组类型(GenericArrayType):并不是我们平常所使用的数组String[] 、byte[]。而是带有泛型的数组,即 T[]
  • 类型变量(TypeVariable):是各种类型变量的公共父接口,就是泛型里面的类似T、E。 在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型;
  • 基本类型(Class):也就是我们所说的java 基本类型,即int、float、double等

Type类几乎在各种框架中都能看到,尤其是涉及代理,反射的业务。理解好Type类也会对今后框架封装,源码解读有很大好处

Type 与子类,子接口的关系

在这里插入图片描述

Class

当需要描述的类型是:

  • 普通的java类(比如String,Integer,Method等等)
  • 数组
  • 自定义类(比如我们自己定义的TestReflect类)
  • java基本类型(比如int,float等)
  • 可能还有其他的类

那么java会选择Class来作为这个Type的实现类,我们甚至可以直接把这个Type强行转换类型为Class。
这些类基本都有一个特点:基本和泛型无关,其他4种Type的类型,基本都是泛型的各种形态

Type

public interface Type {
    @RecentlyNonNull
    default String getTypeName() {
        throw new RuntimeException("Stub!");
    }
}

ParameterizedType (参数化类型)

ParameterizedType 是参数化类型,即泛型,类似List、Map<Integer, String>、List<? extends Number>带有类型参数的类型,也可以是自定义的,再调用getRawType()与getActualTypeArguments()两个方法,就可以得到声明此参数化类型的类(java.lang.Comparable)和实际的类型参数数组([? super T]),而这个? super T又是一个WildcardType类型。

 // 获取泛型的类型,比如 Map<Integer,String> 获取的是 Integer和String
    Type[] getActualTypeArguments();
    // 获取<> 前面的类型,比如 Map<Integer,String> 获取的是Map
    Type getRawType();
    // 如果这个类型是某个类型所属,则获取这个所有者的类型,否则返回null,比如Map.Entry<Sting,String>,会返回Map
    Type getOwnerType();


	//举例
	//参数,List<String>[] p3
	public class TestReflect {
		public static void test(
	            List<TestReflect> p1,
            	Map<String, TestReflect> p2
	    ) {}
    }
    Method[] methods = TestReflect.class.getMethods();
    Method method=methods[i].eques("test");
    Type[] types=method.getGenericParameterTypes();
    //第一个参数 List<TestReflect> p1
    Type type3=types[0];
    Type[] parameterizedType1=((ParameterizedType)type1).getActualTypeArguments();
    Class parameterizedType1_0=(Class)parameterizedType1[0];
    System.out.println("获取泛型的类型 :"+parameterizedType1_0.getName());
    //【打印log】 获取泛型的类型 :com.wf.javatype.TestReflect

	//第二个参数,Map<String,TestReflect> p2
    Type type2=types[2];
    Type[] parameterizedType2=((ParameterizedType)type2).getActualTypeArguments();
    Class parameterizedType2_0=(Class)parameterizedType2[0];
    System.out.println("获取泛型的类型 1:"+parameterizedType2_0.getName());
    Class parameterizedType2_1=(Class)parameterizedType2[1];
    System.out.println("获取泛型的类型 2:"+parameterizedType2_1.getName());
    //【打印log】
    //获取泛型的类型 1:java.lang.String
	//获取泛型的类型 2:com.wf.javatype.TestReflect

GenericArrayType (泛型数组类型)

泛型数组类型,用来描述ParameterizedType、TypeVariable类型的数组;即List[] 、T[]等

public interface GenericArrayType extends Type {
    /**
     *  获取泛型数组中元素的类型,要注意的是:
  无论从左向右有几个[]并列,这个方法仅仅脱去最右边的[]之后剩下的内容就作为这个方法的返回值。
     */
    Type getGenericComponentType();

	//举例1
	//参数,List<String>[] p3
	public class TestReflect {
		public static void test(
	            List<String>[] p3,
	            Map<String,TestReflect>[] p4
	    ) {}
    }
    Method[] methods = TestReflect.class.getMethods();
    Method method=methods[i].eques("test");
    Type[] types=method.getGenericParameterTypes();
    Type type3=types[0];
    Type genericArrayType3=((GenericArrayType)type3).getGenericComponentType();
    System.out.println("类型 :"+genericArrayType3.getTypeName());
    //【打印log】 类型 :java.util.List<java.lang.String>
	
	//举例2
	Type type4=types[1];
    Type genericArrayType4=((GenericArrayType)type4).getGenericComponentType();
    ParameterizedType parameterizedType4=(ParameterizedType)genericArrayType4;
    System.out.println("获取泛型类型 :"+parameterizedType4.getTypeName());
    //【打印log】获取泛型类型 :java.util.Map<java.lang.String, com.wf.javatype.TestReflect>
    Type[] parameterizedType4Arr=parameterizedType4.getActualTypeArguments();
    Class class4_0=(Class)parameterizedType4Arr[0];
    System.out.println("获取泛型类型 1:"+class4_0.getName());
    //【打印log】获取泛型类型 1:java.lang.String
    Class class4_1=(Class)parameterizedType4Arr[1];
    System.out.println("获取泛型类型 2:"+class4_1.getName());
    //【打印log】获取泛型类型 2:com.wf.javatype.TestReflect
}

TypeVariable (类型变量类型)

类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类;在这需要强调的是,TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型;


public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    // 获取泛型的上限,无显示定义(extends),默认为Object
    Type[] getBounds();
    // 获取声明改类型变量实体(即获取类,方法或构造器名)
    D getGenericDeclaration();
    // 获取名称,即K、V、E之类名称
    String getName();
    // 
     AnnotatedType[] getAnnotatedBounds();

认识TypeVariable之前,我们先来看另一个接口 GenericDecalaration;
GenericDeclaration 有三个直接子类 Class、Construtor、Method、Executable也就是说只能在这几种对象上进行范型变量的声明(定义)。

GenericDeclaration

//1.在类(Class)上声明(定义)类型变量
class A<T>{
  T a;
}//之后这里可用任意类型替换T,例如
A<String> as = new A<String>();
//是否看着有点像集合?不错,集合就是泛型的一个典型运用

//2.在方法上声明(定义,方法上,类型变量声明(定义)不是在参数里边,而且必须在返回值之前,static等修饰后
public <E> void test(E e){}


//3.声明(定义)在构造器上
public <K> A(K k){}

//4. 第四种没有使用过,有会的大佬可以指点我一下

【注意】:类型变量声明(定义)的时候不能有下限(super),否则编译器报错。为什么T extend classA 表示泛型有上限classA 可以,因为每一个传进来的类型必定是classA(具有classA 的一切属性和方法) ,但若是T super classA,传进来的类型不一定具有classA的属性和方法,当然就不使用与泛型

【extends 和 super的区别】

关键字说明
 ? 通配符类型
<? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
<? super T> 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
看了这个我是不太明白,换成白话是这个意思:
List<? extends T> 是说 这个list放的是T或者T的子类型的对象,但是不能确定具体是什么类型,所以可以get(),不能add()(可以add null值)

List<? super T> 是说这个list放的是至少是T类型的对象,所以我可以add T或者T的子类型,但是get得到的类型不确定,所以不能获取

WildcardType (泛型表达式或者通配符表达式)

当需要描述的类型是泛型类,而且泛型类中的泛型被定义为(? extends xxx)或者(? super xxx)这种类型,比如List<? extends TestReflect>,这个类型首先将由ParameterizedType实现,当调用ParameterizedType的getActualTypeArguments()方法后得到的Type就由WildcardType实现。

public interface WildcardType extends Type {
	//得到的是类型的上边界的Type数组,实际上就是类型的直接父类,也就是extends后面的类型。
	//显然在当前java的设定中,这个数组只可能有一个元素,因为java现在只能extends一个类。如果实在没写extends,那他的直接父类就是Object
    @RecentlyNonNull
    Type[] getUpperBounds();

    //得到的是类型的下边界的Type数组,有super关键字时可能会用到,经测试不会得到类型的子类,
    //而是只得到super关键字后面的类型,如果没写super关键字,则返回空数组。
    @RecentlyNonNull
    Type[] getLowerBounds();
}

示例

public class TestReflect {

    public static void test(
            TestReflect p0,
            List<TestReflect> p1,
            Map<String, TestReflect> p2,
            List<String>[] p3,
            Map<String, TestReflect>[] p4,
            List<? extends TestReflect> p5,
            Map<? extends TestReflect, ? super TestReflect> p6
    ) {}
}

@Test
public  void main() {
	//获取 TestReflect 类的所有方法
	Method[] methods = TestReflect.class.getMethods();
	for (int i = 0; i < methods.length; i++) {
            Method method=methods[i];
            if(method.getName().equals("test")){
                System.out.println("TestReflect 的 方法: "+method.getName());
                Type[] types=method.getGenericParameterTypes();

                //第一个参数,TestReflect p0
                Class type0=(Class)types[0];
                //【打印log】 type0 :com.wf.javatype.TestReflect
                System.out.println("type0 :"+type0.getName());

				//第二个参数,List<TestReflect> p1
                //获取泛型的类型
                Type type1=types[1];
                Type[] parameterizedType1=((ParameterizedType)type1).getActualTypeArguments();
                Class parameterizedType1_0=(Class)parameterizedType1[0];
                //【打印log】获取泛型的类型 :com.wf.javatype.TestReflect
                System.out.println("获取泛型的类型 :"+parameterizedType1_0.getName());


				//第三个参数,Map<String,TestReflect> p2
                Type type2=types[2];
                Type[] parameterizedType2=((ParameterizedType)type2).getActualTypeArguments();
                Class parameterizedType2_0=(Class)parameterizedType2[0];
                //【打印log】 获取泛型的类型 1:java.lang.String
                System.out.println("获取泛型的类型 1:"+parameterizedType2_0.getName());
                Class parameterizedType2_1=(Class)parameterizedType2[1];
                //【打印log】获取泛型的类型 2:com.wf.javatype.TestReflect
                System.out.println("获取泛型的类型 2:"+parameterizedType2_1.getName());
            }
        }
}

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

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

相关文章

shell练习之安全脚本

题目&#xff1a; 将密码输入错误超过4次的IP地址通过firewalld防火墙阻止访问 1.初始配置 首先使用systemctl工具启用firewalld服务&#xff1a; ​[rootlocalhost ~]# systemctl enable firewalld如果已经启用了&#xff0c;我们现在可以通过执行以下命令启动firewalld&a…

失败就是差一点的成功,社科院与杜兰大学金融管理硕士项目为你在职读研助力

失败的人&#xff0c;只差了一点点&#xff1b;成功的人&#xff0c;是多做了一点点&#xff1b;顶尖的人&#xff0c;则是再多做一点点。小事成就大事&#xff0c;细节成就完美&#xff0c;所以&#xff0c;千万不要只差那么一点&#xff0c;就放弃了。都说失败是成功之母&…

从Reactor模式俯瞰Nginx,你会发现你与高手的差距就在设计模式上

我们知道了Nginx是做什么的以及它为何如此高效&#xff0c;以至于全宇宙拿它来做负载均衡或者说web server。 但是如果你只是了解了使用和知道了原理就认为已经掌握了它&#xff0c;那只能说你肤浅了&#xff0c;原理和使用技能看看大家都知道了&#xff0c;没必要拿出去和别人…

快排递归、迭代的实现和两种优化方法

目录 快速排序 实现代码 时间复杂度 快排的优化 随机选择策略 三位取中法 非递归的快排 快速排序 快速排序算法是基于分治策略的一个排序算法&#xff0c;其基本思想是对于输入的子数组进行分解、递归求解&#xff0c;最后合并。 分解&#xff1a;以数组中左边第一个数作…

运行flutter doctor命令检测环境是否配置成功报错及解决方案

/** 运行flutter doctor命令检测环境是否配置成功&#xff0c;报如下错误**/ 1. cmdline-tools component is missing & Android licenses status unknown 1.1.安装cmdline-tools 1.2.配置android-licenses 运行命令flutter doctor --android-licenses&#xff0c;提示…

封装一个帧动画组件,使用的是精灵图

我写的是淘宝小部件&#xff0c;限制很多&#xff0c;用的是精灵图&#xff0c;说下大概思路&#xff0c;主要是通过背景图片的X Y轴去控制&#xff0c;首先创建一个组件 例&#xff1a; 然后在props定义需要的参数&#xff0c;可通过父组件传递修改 需要传入精灵图地址、单…

【云原生】Prometheus监控docker容器

部署node-exporter用于搜集硬件和系统信息 // 全部主机都要做 docker run -d -p 9100:9100 -v /proc:/host/proc -v /sys:/host/sys -v /:/rootfs --nethost prom/node-exporter --path.procfs /host/proc --path.sysfs /host/sys --collector.filesystem.ignored-mount-point…

Windows系统pagefile.sys删除、移动

背景 在使用windows系统中通常会发现c盘系统盘容量和实际容量不符。以至于你以为还有几十个G的空间&#xff0c;但操作程序时会出现空间不足的情况 。 例如以下错误&#xff1a; # There is insufficient memory for the Java Runtime Environment to continue. # Native memo…

【六】Netty Google Protobuf 编解码

Netty Google Protobuf 编解码Google Protobuf 介绍Protobuf 的入门Protobuf 开发环境搭建Protobuf 下载创建.proto文件第五节的 对应实体&#xff08;SubscribeReq&#xff0c;SubscribeResp &#xff09;SubscribeReq.proto 文件SubscribeResp.proto利用命令生成对应的java文…

详解c++---string模拟实现

这里写目录标题前言准备工作构造函数析构函数迭代器的实现插入数据有关的函数实现reservepush_backoperatorappendinserterasefindresize[ ]clear>>>>新式拷贝构造函数新式赋值重载前言 在前面的文章里我们学习了c中string的用法&#xff0c;那么这篇文章我们将带…

Vue的双向绑定(数据劫持)

双向绑定所谓的双向绑定其实就是&#xff0c;ui或者数据有一方做了修改&#xff0c;那么另外一个也会随着改变。简单来说&#xff0c;视图驱动数据&#xff0c;同时数据也能驱动视图。视图驱动数据&#xff0c;只需要绑定事件。数据驱动视图&#xff0c;则需要去对数据做监听&a…

DC-DC PCB layout经验-含走线宽度和载流量表格

在DC-DC芯片的应用设计中&#xff0c;PCB布板是否合理对于芯片能否表现出其最优性能有着至关重要的影响。不合理的PCB布板会造成芯片性能变差如线性度下降&#xff08;包括输入线性度以及输出线性度&#xff09;、带载能力下降、工作不稳定、EMI辐射增加、输出噪声增加等&#…

不同Nodejs版本的TypeScript的建议配置

Node Target Mapping microsoft/TypeScript Wiki GitHubTypeScript is a superset of JavaScript that compiles to clean JavaScript output. - Node Target Mapping microsoft/TypeScript Wikihttps://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping以上是tsc…

SpringBoot+Vue项目知识管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…

macOS 安装 Frama-C 及使用

操作系统&#xff1a;macOS 12.6 Monterey 官网安装指导&#xff1a;Get Frama-C 一、操作与避坑 &#x1f573;️ 1、macOS 包管理绕不开 Homebrew 工具&#xff0c;确保安装好。 2、安装 Frama-C 的必要依赖 brew install opam gmp gtk gtksourceview libgnomecanvas在安装…

MATLAB-最大值与最小值

在MATLAB中&#xff0c;用于计算最大值的函数是max函数&#xff0c;用于计算最小值的函数是min函数&#xff0c;其调用格式如下。Bmax(A) %计算最大值 &#xff0c;若A为向量&#xff0c;则计算并返回向量中的最大值;若A为矩阵&#xff0c;则计算并返回%一个含有各列最大值的行…

从0到1完成一个Vue后台管理项目(九、引入Breadcrumb面包屑,更改bug)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

ansible(第四天)

三&#xff1a;编写playbook 1.Ansible playbook 临时命令可以作为一次性对一组主机运行简单的任务。不过&#xff0c;若要真正发挥Ansible的力量&#xff0c;需要了解如 何使用playbook可以轻松重复的方式对一组主机执行多项复杂的任务。 play是针对对清单中选定的主机运行…

汽车电子系统网络安全组织管理

声明 本文是学习GB-T 38628-2020 信息安全技术 汽车电子系统网络安全指南. 下载地址 http://github5.com/view/764而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 汽车电子系统网络安全组织管理 6.1 组织机构设置 组织应高度重视网络安全&#xff0c…

基于Prometheus+Grafana搭建监控平台(Windows/Linux环境exporter部署)

1. 介绍 1.1 Prometheus是什么?Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云计算基金会…