Java泛型中 T 和 ? 傻傻分不清楚

1.定义:
JDK5.0后,Java提供了泛型。
泛型是一种在编译时提供类型安全的方式,允许程序员在定义类、接口和方法时使用类型参数。这样,可以在不损失类型安全的情况下,创建可重用的代码。
泛型有两种主要的使用形式:类型参数(如 T)和通配符(如 ?)。
T通常用作类型参数的占位符。比如:泛型方法的语法包括一个包含在尖括号内的类型参数列表,并将它置于方法的返回类型之前。
?通配符主要用于泛型方法的参数和泛型类的字段,以及泛型集合的声明中。

通配符分为3种,分别为:
1)上界通配符:List<? extends Number>
可以读取容器内的元素。由于容器的具体类型未知,如果往容器添加元素,无法确保添加进去的具体数据是该容器具体类型的子类还是父类,因此存在类型不安全问题,所以是不允许往容器里添加数据的。
2)无界通配符:List<?>
3)下界通配符:List<? super Number>
可以读取也可以写入元素。


2.使用范围:
1)T 用作声明类的类型参数、方法(包括静态泛型方法、非静态泛型方法、泛型构造函数,但类型参数仅限于方法内使用)的类型参数。
2)? 通配符用作 参数类型、字段类型、局部变量类型及返回类型。

通配符在PECS(Producer Extends Consumer Super)原则中非常有用,该原则指出当你从一个泛型集合中获取对象时(生产者),应该使用上界通配符,当你向泛型集合中插入对象时(消费者),应该使用下界通配符。
通配符,一般是用于定义一个引用变量,以便实现"多态"调用(非真正意义上的多态)。例如
//以下是正确的代码:
public static void main(String[] args) {
    List<String> sList = new ArrayList<String>();
    List<Integer> iList = new ArrayList<Integer>();
    sList.add("abc");
    iList.add(10000);
    dump(sList);
    dump(iList);
}
public static void dump(List<?> list) {
    for (Object o : list) {
        System.out.println(o);
    }
}


通常我们使用 ? 的时候并不知道也不关心这个时候的类型,只想使用其通用的方法,而且 ? 通配符是无法作用于声明类的类型参数,一般作用于方法和参数上。而 类型变量 T 在类定义时具有更广泛的应用。

在某些程度的使用上 ? 通配符与 T 参数类型是可以等效的,但是 T 参数类型并不支持下界限制, 即 T super AClass 而 通配符支持下界限制 ? super AClass,即:使用super限定父集的时候,T 不可以,? 可以。
T和?两者都可以通过extends来限定一个类型的子集,但是 T 可以 List<T extends Number & AInterface> 限定为多重限定,? 不可以。
使用T时,Java的类型参数支持多重限定,如 <T extends CharSequence & Comparable<T>,但如果类型参数中包含类,则需要将类参数类型写在最前面。

如果你想写一个通用的方法且该方法的逻辑不关心类型那么就用 ? 通配符来进行适配,如果你需要作用域类型(这可能在操作通用数组类型时更有用)或者声明类的类型参数时请使用 T 类型变量。

//以下是错误的用法(编译错误:通配符不能用在创建对象上):
ArrayList<?> list = new ArrayList<?>();
//以下是错误的用法(List<T>在实例化的时候T要替换成具体的类):
List<T> t = new ArrayList<T>();

类型参数T和通配符?可以混合使用,例如以下为一个接受泛型集合并返回其中最大元素的方法:
public static <T extends Comparable<T>> T max(Collection<? extends T> collection) {  
    T maxElement = null;  
    for (T element : collection) {  
        if (maxElement == null || element.compareTo(maxElement) > 0) {  
            maxElement = element;  
        }  
    }  
    return maxElement;  
}


3.总结:
当对通用的对象类型进行操作时,使用 Object的缺点为:无法对 Object 编译时进行检查,因为 Object 是所有类的父类。
? 表示了集合[所有Java类型,包括String,Integer,Character等系统定义的,或者用户定义的类型]这个整体;而 T 表示了集合[所有Java类型,包括String,Integer,Character等系统定义的,或者用户定义的类型]中的一个成员。

当Integer类是Number类的子类时,List<? extends Integer>是List<? extends Number>的子类,而List<Integer>不是List<Number>类的子类。
可以向 List<Object> 中插入 Object 对象或者其子类对象,但只能向 List<?> 中插入 null 值,因为List<?>无法确定插入的元素的类型,而null是所有类型的成员。
类型参数写成全大写的有意义的单词是更具可读性的方式。


致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享。

若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢。您的支持是我们为您提供帮助的最大动力。

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

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

相关文章

linux学习:栈

目录 顺序栈 结构 初始化一个空顺序栈 压栈 出栈 例子 十进制转八进制 链式栈 管理结构体的定义 初始化 压栈 出栈 顺序栈 顺序栈的实现&#xff0c;主要就是定义一块连续的内存来存放这些栈元素&#xff0c;同时为了方便管理&#xff0c; 再定义一个整数变量来代表…

2024中国(宁波)国际宠物用品博览会

2024中国(宁波)国际宠物用品博览会 People&Pet Fair 2024 专注2B交易&#xff0c;关注人宠发展&#xff0c;它经济&#xff0c;势不可挡! 时间&#xff1a;2024年11月14-16日 地点&#xff1a;宁波国际会展中心 详询主办方陆先生 I38&#xff08;前三位&#xff09; …

水离子雾化壁炉与酒店大厅的氛围搭配

将水离子雾化壁炉与酒店大厅的氛围搭配是一个很好的主意&#xff0c;可以为大厅增添舒适、温馨的氛围&#xff0c;以下是一些建议&#xff1a; 迎宾区域&#xff1a;在酒店大厅的迎宾区域设置水离子雾化壁炉&#xff0c;作为客人抵达时的第一印象。壁炉的温馨效果可以让客人感到…

Java+BS +saas云HIS系统源码SpringBoot+itext + POI + ureport2数字化医院系统源码

JavaBS saas云HIS系统源码SpringBootitext POI ureport2数字化医院系统源码 医院云HIS系统是一种运用云计算、大数据、物联网等新兴信息技术的业务和技术平台。它按照现代医疗卫生管理要求&#xff0c;在特定区域内以数字化形式收集、存储、传递和处理医疗卫生行业的数据。通…

【应用】SpringBoot-自动配置原理

前言 本文简要介绍SpringBoot的自动配置原理。 本文讲述的SpringBoot版本为&#xff1a;3.1.2。 前置知识 在看原理介绍之前&#xff0c;需要知道Import注解的作用&#xff1a; 可以导入Configuration注解的配置类、声明Bean注解的bean方法&#xff1b;可以导入ImportSele…

前置递增和后置递增

前置递增 先让变量1&#xff0c;然后进行表达式运算 int a2 10;int b2 a2 *10;cout<<"a2"<<a2<<endl;cout<<"b2"<<b2<<endl;运行结果&#xff1a;a211 b2110 后置递增 后置递增&#xff0c;先进行表达式运算&…

Python pathlib中Path用法

Python pathlib中Path用法 文章目录 Python pathlib中Path用法 Path类是Python中 pathlib模块的主要组成部分之一&#xff0c;它提供了一种面向对象的方式来处理文件系统路径。 Path对象可以表示文件路径或目录路径&#xff0c;并且可以执行各种与路径相关的操作&#xff0c;…

异构超图嵌入的图分类 笔记

1 Title Heterogeneous Hypergraph Embedding for Graph Classification&#xff08;Xiangguo Sun , PictureHongzhi Yin , PictureBo Liu , PictureHongxu Chen , PictureJiuxin Cao , PictureYingxia Shao , PictureNguyen Quoc Viet Hung&#xff09;【WSDM 2021】 2 Co…

模拟移动端美团案例(react版)

文章目录 目录 概述 项目搭建 1.启动项目&#xff08;mock服务前端服务&#xff09; 2.使用Redux ToolTik(RTK)编写store(异步action) 3.组件触发action并渲染数据 一、渲染列表 ​编辑 二、tab切换类交互 三、添加购物车 四、统计区域功能实现 五、购物车列表功能实现 六、控制…

Leetcode算法训练日记 | day23

一、修剪二叉搜索树 1.题目 Leetcode&#xff1a;第 669 题 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff…

netty实现mqtt(IOT)

springbootnettymqtt服务端实现 springbootnettymqtt客户端实现 MQTT协议基本讲解(结合netty) 李兴华netty视频教程中mqtt讲解 EMQX官网、mqttx客户端 IOT云平台 simple&#xff08;6&#xff09;springboot netty实现IOT云平台基本的架构&#xff08;mqtt、Rabbitmq&…

2024/4/2—力扣—最小高度树

代码实现&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* buildTree(int *nums, int l, int r) {if (l > r) {return NULL; // 递归出口}struct…

<script setup>组件内的路由守卫

在 Vue 3 中&#xff0c;<script setup> 提供了更简洁的方式来编写组件逻辑&#xff0c;但这并不意味着不能在其中编写路由守卫。然而&#xff0c;路由守卫通常是在全局、路由独享或组件内&#xff08;在 Vue 2 中是通过 beforeRouteEnter、beforeRouteUpdate 和 beforeR…

钩子函数和副作用

Person: react中父组件想要获得子组件的state内容&#xff0c;可以如何实现 ChatGPT: 在React中&#xff0c;父组件可以通过props向子组件传递一个回调函数&#xff0c;子组件在适当的时机调用这个回调函数&#xff0c;并将需要传递的state内容作为参数传递给父组件。这样就…

Cohere推出全新升级版RAG大型AI模型:支持中文,搭载1040亿参数,现开源其权重!

4月5日&#xff0c;知名类ChatGPT平台Cohere在其官方网站上发布了一款全新的模型——Command R。 据官方消息&#xff0c;Command R拥有1040亿个参数&#xff0c;并且支持包括英语、中文、法语、德语在内的10种语言。这一模型的显著特点之一在于其对内置的RAG&#xff08;检索增…

论文复现:torch.max(p,1)

在 PyTorch 中&#xff0c;torch.max 函数用于计算张量&#xff08;tensor&#xff09;的最大值。当你对 torch.max 使用两个参数时&#xff0c;第一个参数是你要操作的张量&#xff0c;第二个参数是维度&#xff08;dimension&#xff09;沿着该维度进行操作。函数会返回两个对…

程序“猿”初学者学习计划

下面是一个为初学者量身定制的学习计划。这个计划假设你是从零开始&#xff0c;并将引导你逐步进入编程世界。记住&#xff0c;学习编程是一场马拉松&#xff0c;不是冲刺&#xff0c;所以保持耐心&#xff0c;持续学习是关键。 第一阶段&#xff1a;基础入门&#xff08;1-2个…

P3613洛谷:深积 P5741旗鼓相当 %P1104生日 set题海战

1-用map可以实现数组对应数值&#xff0c;再用vec传输。 #include<bits/stdc.h> using namespace std; int n, q, mes, x, y, val; typedef pair<int, int> pr; map<pr, int> mp; vector<int> vec;int main(){cin >> n >> q;for(int i 0…

文件加密软件大全,按市场份额排名

文件加密软件大全&#xff0c;按市场份额排名 文件加密是一种保护数据安全的重要手段&#xff0c;通过使用特定的算法将明文文件转化为密文&#xff0c;以防止未经授权的访问、篡改或泄露&#xff0c;市场份额排名的八款软件你需要了解一下。 1、安企神软件 专注于加密和审计…

高阶流程图(SIPOC)

SIPOC高阶流程图是一种流程映射和改进方法&#xff0c;它使用可视化的方式描述一个或多个流程的输入和输出。SIPOC是五个单词的首字母缩写&#xff0c;分别代表供应商&#xff08;Suppliers&#xff09;、输入&#xff08;Inputs&#xff09;、过程&#xff08;Processes&#…