Java 泛型方法

article/2025/10/15 20:22:01

本文包含:

  1. 定义泛型方法
  2. 泛型方法和类型通配符的区别
  3. Java 7 的“菱形”语法与泛型构造器
  4. 设定通配符·下限
  5. 泛型方法与方法重载
  6. Java 8 改进的类型推断

1. 定义泛型方法

假设需要实现这样一个方法:该方法负责将一个 Object 数组的所有元素添加到一个 Collection 集合中。考虑采用如下代码来实现该方法:
在这里插入图片描述
上面定义的方法没有任何问题,关键在于方法中的c 参数,它的数据类型是 Collection。正如前面介绍的,Collection 不是 Collection 的子类型—所以这个方法的功能很有限,它只能将 Object[] 数组的元素复制到元素为 Object (Object 的子类不行)的Collection 集合中,即下面代码会引起问题。
在这里插入图片描述
可见上面方法的参数类型不可以使用 Collection,
使用通配符 Collection<?> 也不行,因为Java 不允许把对象放进一个未知类型的集合里。
为解决这个问题,可以使用 Java 5 提供的泛型方法,在声明方法时定义一个或多个类型形参。泛型用法格式如下:
在这里插入图片描述
该泛型方法的方法签名比普通方法的方法签名多了类型形参声明,类型形参声明以尖括号括起来,多个类型形参直接以逗号(,)隔开,所有的类型形参声明放在方法修饰符和返回值类型之间。
采用支持泛型的方法,就可以将上面的 fromArrayToCollection 方法改写为如下形式:
在这里插入图片描述
下面程序示范了完整用法:
在这里插入图片描述
在这里插入图片描述
上面程序调用了一个泛型方法,该泛型方法中定义了一个 T 类型形参,这个 T 类型形参就可以在该方法内当成普通类型使用。与接口、类声明中定义的类型参数不同的是,方法声明中定义的形参只能在该方法内使用,而接口、类声明中定义的类型形参则可以在整个接口、类中使用。

与类,接口中泛型参数不同的是,方法中的泛型参数无须显式传入实际类型参数,如上面程序所示,当程序调用 fromArrayToCollection() 方法时,无须在调用该方法前传入String、Object 等类型,但系统依然可以知道类型参数的数据类型,因为编译器根据实参推断类型实参的值,它通常推断出最直接的类型参数。例如,下面调用程序:
在这里插入图片描述
上面代码中 cs 是一个 Collection 类型,与方法定义时的 fromArrayToCollection(T[] a, Collection c)进行比较—只比较泛型参数,不难发现该 T 类型形参代表的实际类型是 String 类型。
对于如下调用代码:
在这里插入图片描述
上面的 cn 是Collection 类型,与此方法的方法签名进行比较—只比较泛型参数,不难发现该T 类型形参代表了 Number 类型。
在下面程序中:
在这里插入图片描述在这里插入图片描述
上面程序中定义了 test() 方法,该方法用于将前一个集合中的元素复制到下一个集合中,该方法中的两个形参from、to 的类型都是 Collection,这要求调用该方法时的两个集合实参中的泛型类型相同,否则编译器无法准确地推断出泛型方法中类型形参的类型。

上面程序中定义了 test() 方法,该方法用于将集合中的元素复制到下一个集合中,该方法中的两个形参from、to 的类型都是 Collection,这要求调用该方法时的两个集合实参中的泛型类型相同,否则编译器无法准确地推断出泛型方法中类型形参的类型。

上面程序中调用 test 方法传入两个实际参数,其中 as 的数据类型是 List,而 ao 的数据类型是 List,与泛型方法签名进行对比:test(Collection a,Collection c>,编译器无法正确识别 T 所代表的实际类型。
为了避免此错误,可将方法改为如下:
在这里插入图片描述在这里插入图片描述

2. 泛型方法和类型通配符的区别

大多数时候都可以使用泛型方法来代替类型通配符。例如,对于 Java 的Collection 接口中两个方法定义:
在这里插入图片描述
上面集合中两个方法的形参都采用了类型通配符的形式,也可以采用泛型方法的形式,如下所示:
在这里插入图片描述
上面方法使用了 泛型形式,这时定义类型形参时设定上限(其中 E 是Collection 接口里定义的类型形参,在该接口里 E 可以当成普通类型使用)
上面两个方法中类型形参 T 只使用了一次,类型形参 T 产生的唯一效果是可以在不同的调用点传入不同的实际类型。对于这种情况,应该使用通配符。通配符就是被设计用来支持灵活的子类化的。
泛型方法允许类型形参被用来表示方法的一个或多个参数之间的依赖关系,或者方法返回值与参数之间的类型依赖关系。如果没有这样的类型依赖关系,就不应该使用类型方法。
在这里插入图片描述
如果有需要,也可以同时使用泛型方法和通配符,如 Java 的 Collections.copy()方法。
在这里插入图片描述
在这里插入图片描述

3. Java 7 的“菱形”语法与泛型构造器

泛型构造器可以在构造器签名中声明类型形参,那么在调用构造器时就可以根据数据类型来推断类型形参的类型,程序员也可以显式的为构造器中的类型形参指定实际的类型。

在这里插入图片描述

4. 设定通配符下限

假设自己实现一个工具方法:实现将 src 集合里的元素复制到 dest 集合里的功能,因为 dest 集合可以保存 src 集合里的所有元素,所以 dest 集合元素里的类型应该是 src 集合元素类型的父类。为了表示两个参数之间的类型依赖,可以考虑同时使用通配符、泛型参数来实现这些方法。
在这里插入图片描述
上面方法实现了前面的类型。现在假设该方法需要一个返回值,返回最后一个被复制的元素,则可以把上面方法改为如下形式:
在这里插入图片描述
在遍历 src 集合元素时,src 元素的类型是不确定的(只可以肯定它是 T 的子类),程序只能用 T 来笼统表示各种 src 集合的元素类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
使用这种语句,可以保证程序的 1 处调用后推断出最后一个被复制的元素类型是 Integer,而不是笼统的 NUmber 类型。
实际上, Java 集合框架中的 TreeSet 有一个构造器也用到了这种设定通配符下限的语句,如下所示:
在这里插入图片描述
TreeSet 会对集合中的元素按自然顺序或定制顺序进行排序。如果需要 TreeSet 对集合中的所有元素进行定制排序,则要求 TreeSet 对象有一个与之关联的 Comparator 对象。上面构造器中的参数 c 就是进行定制排序的 Comparator 对象。
Comparator 接口也是一个带泛型声明的接口:
在这里插入图片描述
通过这种带下限的通配符的语法,可以在创建 TreeSet 对象时灵活选择合适的 Comparator 。假定需要创建一个 TreeSet 集合,并传入一个可以比较 String 大小的 Comparator,这个 Comparator 既可以是 Comparator,也可以是 Comparator —只要尖括号里传入的类型是String 的父类型(或它本身)即可。
在这里插入图片描述
通过使用这种通配符下限的方式来定义 TreeSet 构造器的参数,就可以将所有可用的 Comparator 作为参数传入,从而增加了程序的灵活性。当然,不仅 TreeSet 有这种用法,TreeMap 也有类似的用法。

5. 泛型方法与方法重载

因为泛型既允许设定通配符的上限,也允许设定通配符的下限,从而允许在一个类里包含如下两个方法定义:
在这里插入图片描述
在这里插入图片描述
上面的 MyUtils 类中包含两个 copy() 方法,这两个方法的参数列表有区别。
在这里插入图片描述

6. Java 8 改进的类型推断

类型推断主要有如下两个方面:

  1. 可通过调用方法的上下文来推断类型参数的目标参数
  2. 可在方法调用链中,将推断得到的类型参数传递到最后一个方法。
    在这里插入图片描述
    上面程序中前两行粗体字代码的作用完全相同,但第一行代码无须在调用 MyUtil 类的 nil()方法时显式指定类型参数为 String ,这是因为程序需要将该方法的返回值赋值给 MyUtil类型,因此系统可以自动推断出此处的类型参数为 String 类型。
    上面程序中第 3 行与第 4 行粗体字代码的作用也完全相同,但第 3 行粗体字代码也无须在调用 MyUtil 类的 nil() 方法时显式指定类型参数为 Integer,这是因为程序将 nil() 方法的返回值作为了 MyUtil 类的 cons() 方法的第二个参数,而程序可以根据 cons() 方法的第一个参数(42)推断出此处的类型参数为 Integer 类型。
    虽然 Java 8 增强了泛型推断的能力,但也不是万能的。下面代码就是错的:
    在这里插入图片描述
    因此,上面这行代码必须显式指定类型参数,即将代码改为如下形式:
    在这里插入图片描述

http://chatgpt.dhexx.cn/article/GtxYlg37.shtml

相关文章

【java】泛型方法的定义

一、定义泛型方法的格式 二、调用泛型方法的语法格式 三、解释 1、定义泛型方法时&#xff0c;必须在返回值前边加一个<T>&#xff0c;来声明这是一个泛型方法&#xff0c;持有一个泛型T&#xff0c;然后才可以用泛型T作为方法的返回值。 2、Class<T>的作用就是指…

Java 中的泛型(两万字超全详解)

文章目录 前言一、泛型概述1. 什么是泛型&#xff1f;为什么要使用泛型&#xff1f;2. 泛型使用场景3. 泛型概述小结 二、泛型类1. 泛型类的定义2. 泛型类的使用 三、泛型接口四、泛型方法1. 泛型方法的定义2. 泛型方法的使用3. 泛型方法中的类型推断 五、类型擦除1. 什么是类型…

Java中的泛型方法

泛型是什么意思在这就不多说了&#xff0c;而Java中泛型类的定义也比较简单&#xff0c;例如&#xff1a;public class Test{}。这样就定义了一个泛型类Test&#xff0c;在实例化该类时&#xff0c;必须指明泛型T的具体类型&#xff0c;例如&#xff1a;Test t new Test();&am…

【软件测试】使用C++ Test进行动态测试

测试目的 1.掌握动态测试的方法。 2.掌握使用Parasoft C Test进行动态测试。 测试环境 Windows XP, Parasoft C Test 9.2 测试内容 使用Parasoft C Test进行动态测试&#xff0c;包括自动化测试、自定义测试用例、数据源测试用例、桩函数机制。 测试过程及结果 4.1 基于…

测试基础-动态白盒测试

1.动态白盒测试 定义&#xff1a;也称结构化测试。利用查看代码功能&#xff08;作什么&#xff09;和实现方式&#xff08;怎么做&#xff09;得到的信息来确定哪些需要测试、哪些不需要测试、如何开展测试。 动态白盒测试包括以下4个部分&#xff1a; 直接测试底层函数、过…

符合功能安全要求的动态测试工具-TESSY

Tessy是一个专门针对嵌入式软件的C/C代码进行单元、集成测试的工具&#xff0c;它可以自动化地执行测试、评估测试结果并生成测试报告。 Tessy的目标就是&#xff1a;通过自动化整个测试周期&#xff0c;支持针对C语言的单元测试/集成测试&#xff0c;同时&#xff0c;Tessy也…

软件测试复习03:动态测试——白盒测试

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录 逻辑覆盖法&#xff1a;最常用程序插桩技术基本路径法点覆盖边覆盖边对覆盖主路径覆盖 符号测试错…

动态测试

动态测试 1.1 动态分析技术 虽然静态分析技术不需要软件的执行&#xff0c;而从动态分析本身来看更像是一个“测试”。它包含了系统的执行。当软件系统在模拟的或真实的环境中执行之前、之中和之后&#xff0c;对软件系统行为的分析是动态分析的主要特点。动态分析包含了程序在…

软件测试复习04:动态测试——黑盒测试

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录 等价划分法边值分析法错误推测法因果图法示例 习题 等价划分法 等价类&#xff1a;一个几何&…

动态测试方法

动态测试方法&#xff0c;通过实际执行代码去发现潜在代码错误的测试方法。 人工动态方法 人工动态方法&#xff0c;可以真正检测代码的业务逻辑功能&#xff0c;其关注点是“什么样的输入&#xff0c;执行了什么代码&#xff0c;产生了什么样的输出”&#xff0c;主要用于发…

linux同步时间服务器时间配置

linux时间同步简单配置如下(centos7.x)&#xff1a; 安装时间服务器(系统一般会自带)&#xff1a; yum install ntp ntpdate -y 时间服务器临时配置(重启该配置失效)&#xff1a; ntpdate 192.133.203.89(时间服务器ip) 时间服务器配置: vim /etc/chrony.conf 进入vim编辑页面…

linux 多台机器修改时间同步

修改东八区 首先第一步&#xff0c;通过命令 &#xff1a;date -R 查看当前系统所在时区。如是0800&#xff0c;则是东八区&#xff0c;也就是我们当下的北京时间&#xff0c;如不是&#xff08;如下图&#xff09;&#xff0c;做如下调整。 命令行键入命令&#xff1a;tzsele…

Linux时间同步:chrony

linux7以上版本都自带chrony服务 如果没有安装&#xff0c;则使用yum安装&#xff0c;如果安装了&#xff0c;请忽略 yum -y install chrony 说明&#xff1a;Chrony由两个程序组成&#xff0c;分别是chronyd和chronyc chronyd是一个后台运行的守护进程&#xff0c;用于调整…

linux同步时间(通过定时任务,按时同步时间)

安装同步器 yum install -y ntpdate同步时间(一次性同步,挂起或关闭虚拟机后时间再次不同步) ntpdate 0.centos.pool.ntp.org制作定时任务,同步时间 安装定时任务 yum –y install crontabs制作一个定时任务,设置开机自启 systemctl enable crond --now配置定时任务文件,添…

Linux同步时间的方法

方法一&#xff1a;非生产时使用 第一种是在所有机器上&#xff0c;使用连接工具的并发命令功能&#xff0c;同时运行修改时间命令&#xff0c;比如执行date -s “2019-05-25 17:00:00” &#xff0c;这个方法适合自己测试环境用 第二种就是安装了一个ntpdate命令&#xff0c…

word中插入visio流程图的操作

1、首先需要将画好的流程图进行保存&#xff0c;注意保存的格式是vsdx 2、新建个word文档&#xff0c;找到插入-对象&#xff0c;打开如下&#xff1a; 3、点击由文件创建-浏览中找到你想插入的对应的visio的文件 4、找到之后&#xff0c;下一步就是直接点击确定&#xff0c;…

Visio如何裁剪图片

参考 Visio如何裁剪图片 - 云社区 - 腾讯云 1、首先点击打开Visio软件&#xff0c;如图所示 2、接着在Visio中装载需要处理的图片&#xff0c;点击文件-打开&#xff0c;如图所示 3、加载图片后&#xff0c;点击选中图片&#xff0c;如图所示 4、此时Visio上方菜单栏&#xf…

visio2019怎么对图片加箭头标注,Visio设置图片作为背景

visio2019怎么对图片加箭头标注&#xff0c;Visio设置图片作为背景 单个图片总时作为一个对象被标注&#xff0c;没办法标注细节&#xff0c;可以将图片作为背景&#xff0c;进行标注 首先&#xff0c;插入&#xff0c;新建页&#xff0c;背景页&#xff0c;把欲编辑的图片放…

流程图软件,visio,安装下载教程

建议&#xff1a;如果是插入到word中&#xff0c;建议使用2013版的visio&#xff0c;通过插入对象的方式&#xff0c;插入到word中。 方法一&#xff1a;插入-对象-新建visio 方法二&#xff1a;visio中画好图&#xff0c;插入-对象-由文件创建 这样的word中的visio对象&…