一文通俗理解为什么需要泛型以及泛型的使用
为什么需要泛型?
public static void main(String[] args) {ArrayList list = new ArrayList();// 由于集合没有做任何限定,任何类型都可以给其中存放list.add("abc");list.add("def");list.add(5);Iterator it = list.iterator();while (it.hasNext()) {// 需要打印每个字符串的长度,就要把迭代出来的对象转成String类型String str = (String) it.next();System.out.println(str.length());}
}
思考:上面这段代码有什么问题吗?如果有,那么出现问题的原因是什么?
编译不报错,但运行发生了报错。
因为没使用泛型,导致我们想使用的时候,一旦强转就会出现类型转换异常,而在我们工作中,其实很多时候,我们都只需要一个集合容器里面放一个类型,如果有多个类型,我们就分多个容器来存放,那么进行约束存放类型的功能,就叫泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查。
泛型的使用
打开ArrayList的源码, 会发现在定义类的时候, 在类名后面加了个,然后这个E, 在多个方法参数里面都进行了使用, 这个E到底是什么?
class ArrayList<E> {public boolean add(E e) { }public E get(int index) { }...
}class ArrayList<String> {public boolean add(String e) { }public String get(int index) { }...
}class ArrayList<Integer> {public boolean add(Integer e) { }public Integer get(int index) { }...
}
我 们 发 现 , 只 要 我 们 在 newArrayList<>()的时候,** 在<>括号里面放什么类型, 那么这个E就是什么类型**,比如我们构建的集合是String类型, 那么 E 就 是 String , 我 们 构 建 的 集 合 是Integer类型, 那么E就是Integer;
当然,这个E是可换成自定义的名字,比如说MyType。
使用泛型定义类
新建一个类,然后在<>里面写一个不存在的类型,这个类型甚至不需要我们创建类,然后为了展示,书写了该属性对应的get和set方法。
public class MyGenericClass<MyType> {
// private E e;
//
// public E getE() {
// return e;
// }
//
// public void setE(E e) {
// this.e = e;
// }private MyType myType;public MyType getMyType() {return myType;}public void setMyType(MyType myType) {this.myType = myType;}}
在测试类中,我们创建了2次之前所构建的类对象,两次所传递的泛型类型是不一样的,但是它都能进行接收,并且接收完成之后,也可以通过调用set方法来进行赋值,也能通过调用get方法来进行输出该数据。
public class TestMyGenericClass {public static void main(String[] args) {//模拟构建ArrayList对象的形式来构建一个MyGenericClass类对象MyGenericClass<String> my = new MyGenericClass<String>();my.setMyType("张三");System.out.println(my.getMyType());//再来创建一次其他类型的泛型MyGenericClass<Integer> my1 = new MyGenericClass<Integer>();my1.setMyType(1001);System.out.println(my1.getMyType());}
}
使用泛型定义接口
public interface MyGenericInterface<E> {void add(E e);E getE();
}
定义了一个带泛型的接口之后,这个接口被使用的时候,可以直接在写implements的时候,就把泛型给写死了,代表定义类的时候就确定好了泛型的类型了。
public class MyImp2 implements MyGenericInterface<String>{@Overridepublic void add(String e) {// TODO Auto-generated method stub}@Overridepublic String getE() {// TODO Auto-generated method stubreturn null;}}
定义了一个带泛型的接口之后,这个接口被使用的时候,也可以在该类上仍然不把泛型的类型给确定,让它在构建该类对象的时候去确定该类型。
public class MyImp1<E> implements MyGenericInterface<E>{@Overridepublic void add(E e) {// TODO Auto-generated method stub}@Overridepublic E getE() {// TODO Auto-generated method stubreturn null;}
}
MyImp2类在使用时无需给出泛型,但MyImp1类在使用时必须指明泛型。
public class TestGenericInterface {public static void main(String[] args) {MyImp1<Integer> my1 = new MyImp1<Integer>();//随着你指定的泛型类型不一样,那么它里面的两个方法参数和返回类型也发生了变化my1.add(1001);//这个类型的创建,不需要你使用泛型了,因为我们在该类构建的时候,就已经确定了父接口的//泛型的类型,所以它的方法都跟着变了,以后就不能发生改变了!MyImp2 my2 = new MyImp2();my2.add("你好");}
}
使用泛型定义方法
在方法的返回值前面如果加上泛型的话,那么参数里面的MyType将会报错,所以,通过泛型在方法上的运用,可以让我们在书写方法重载的时候,变的更加的方便
public class MyGenericMethod {//在修饰词的位置写一个泛型的尖括号,里面随便写个类型//这样的效果同等于在类或者是接口名后加<>,只不过这样//的范围就只局限于当前的方法public <E> void show1(E e) {System.out.println(e.getClass());}public <E> E show2(E e) {return e;}public static void main(String[] args) {MyGenericMethod mm = new MyGenericMethod();mm.show1(123);mm.show1("abc");mm.show1(3.14);System.out.println(mm.show2(123));}
}
通配符
然而,如果设 Foo 是 Bar 的一个子类型(子类或者子接口),而 G 是具有泛型声明的类或接口,G并不是 G 的子类型!这一点非常值得注意,因为它与大部分人的习惯认为是不同的。
造成这个原因是因为泛型不存在继承关系!
类型通配符的上下限
如果你想限制一个方法,限制其参数的泛型类型时,你有两种方式:
-
使用<? extends 类>来约束泛型必须要是该类或者是该类的子类;
-
使用<? super 类>来约束泛型必须要是该类或者是该类的父类;
为什么指定通配符上限的集合不能添加元素?
// 定义一个抽象类 Shape
public abstract class Shape {public abstract void draw(Canvas c);
}
// 定义 Shape 的子类 Circle
public class Circle extends Shape {// 实现画图方法,以打印字符串来模拟画图方法实现public void draw(Canvas c) {System.out.println("在画布" + c + "上画一个圆");}
}
// 定义 Shape 的子类 Rectangle
public class Rectangle extends Shape {// 实现画图方法,以打印字符串来模拟画图方法实现public void draw(Canvas c) {System.out.println("把一个矩形画在画布" + c + "上");}
}
public void addRectangle(List<? extends Shape> shapes) {// 下面代码引起编译错误shapes.add(0, new Rectangle());
}
《java疯狂讲义》给出的答案是:
与使用普通通配符相似的是,shapes.add() 的第二个参数类型是? extends Shape,它表示 Shape 未知的子类,程序无法确定这个类型是什么,所以无法将任何对象添加到这种集合中。
简而言之,这种指定通配符上限的集合,只能从集合中取元素(取出的元素总是上限的类型或其子类),不能向集合中添加元素(因为编译器没法确定集合元素实际是哪种子类型)。
我的更通俗理解:List<? extends Shape> shapes传进来的是一个类别Shape本身或者子类(这里我们假设有子类A和B,且A与B之间不存在继承关系)的集合,如果shapes添加子类A的对象,那万一shapes运行时传进来的是子类B的集合,那么"shapes.add(0, new Rectangle());"这行代码是存在问题的;同理shapes添加Shape的对象也是如此。
因此通配符上限的集合,即<? extends Shape>是无法添加的元素,而通配符下限的集合,即<? super Shape>确可以。因为<? super Shape>传进来的都是Shape的父类,而我们添加的元素只要是Shape类别或者Shape的子类就是合法的。
相关文章:
一文通俗理解为什么需要泛型以及泛型的使用
为什么需要泛型? public static void main(String[] args) {ArrayList list new ArrayList();// 由于集合没有做任何限定,任何类型都可以给其中存放list.add("abc");list.add("def");list.add(5);Iterator it list.iterator();wh…...
凸包算法—— cad c#二次开发
效果如下: 代码如下: using IfoxDemo; //[assembly: CommandClass(typeof(IFoxDemo.凸包class))]//只允许此类快捷键命令 namespace IFoxDemo {public class 凸包class{public static class 凸包助手{/// <summary>/// 计算点集的凸包并返回多段线…...
Eclipse JSP/Servlet 深入解析
Eclipse JSP/Servlet 深入解析 引言 随着互联网的快速发展,Java Web开发技术逐渐成为企业级应用开发的主流。在Java Web开发中,JSP(JavaServer Pages)和Servlet是两个核心组件,它们共同构成了Java Web应用程序的基础。本文将深入解析Eclipse平台下的JSP/Servlet技术,帮…...
grep如何排除多个目录?
在使用 grep 进行文本搜索时,有时候需要排除多个目录,避免在这些目录下进行搜索。下面介绍几种不同的实现方式。 目录 1.使用 -r 和 --exclude-dir 选项(GNU grep) 2.使用扩展正则表达式和 -P 选项(GNU grep&#x…...
linux ollama deepseek等大语言模型的model文件的存储目录
linux ollama deepseek等大语言模型的model文件的存储目录 一、用ollama serve启动的,模型数据存放在: /usr/share/ollama/.ollama/models二、如果在自启动文件中指定了工作目录,则在工作目录下的.ollama/models 1.自启动服务 /etc/system…...
React进阶之React核心源码解析(二)
React核心源码解析 diff单一节点比较diff多节点比较diff两轮遍历比较第一轮比较第二轮比较 Update 状态更新Concurrent Mode diff 一共两个阶段 render:内存中的更新,主要是通过递归的过程,来将react变化的部分,在内存中找到哪些…...
八、OSG学习笔记-
前一章节: 七、OSG学习笔记-碰撞检测-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145558132?spm1001.2014.3001.5501 一、了解OSG图元加载显示流程 本章节代码: OsgStudy/wids CuiQingCheng/OsgStudy - 码云 - 开源中国https:…...
Python实现随机森林(Random Forest)算法
随机森林(Random Forest)是一种集成学习方法,通过构建多个决策树并结合它们的预测结果来提高模型的准确性和稳定性。下面是一个使用Python实现随机森林算法的示例。我们将使用scikit-learn库,它提供了方便的接口来实现随机森林。 …...
平方数列与立方数列求和的数学推导
先上结论: 平方数列求和公式为: S 2 ( n ) n ( n 1 ) ( 2 n 1 ) 6 S_2(n) \frac{n(n1)(2n1)}{6} S2(n)6n(n1)(2n1) 立方数列求和公式为: S 3 ( n ) ( n ( n 1 ) 2 ) 2 S_3(n) \left( \frac{n(n1)}{2} \right)^2 S3(n)(2n(n1)…...
new和malloc的区别
new malloc流程 new new流程 调用operator new 分配内存:在free store 生成对象 free store 可能在 堆 / 自定义的地方 可以认为虚拟内存到物理内存的映射关系早已完成 若分配内存失败(内存空间不够),抛出std::bad_alloc 异常…...
JVM——垃圾回收算法
目录 垃圾回收算法 评价标准: 标记-清除算法: 复制算法: 标记-整理算法: 分代GC: arthas查看分代之后的内存情况: 垃圾回收算法 java是如何实现垃圾回收的呢?简单来说,垃圾回…...
算法日记16:SC68 联通块问题(并查集)
一、题目: 二、题解: 1、看到求联通块问题,我们可以考虑使用DFS/并查集(在这里我们仅介绍并查集) 2、什么是并查集? 2.1:初始化:对于每一个点,我们都对其进行初始化操作pre[i]i pre[i]表示i的…...
Unity-Mirror网络框架-从入门到精通之Pong示例
文章目录 前言示例介绍NetworkManagerPongBallPlayer总结前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。本系列文章将为读者提供对Mirror网络框架的深入了解,涵盖从基础到高级的多个主题。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计…...
c++ 多线程知识汇总
一、std::thread std::thread 是 C11 引入的标准库中的线程类,用于创建和管理线程 1. 带参数的构造函数 template <class F, class... Args> std::thread::thread(F&& f, Args&&... args);F&& f:线程要执行的函数&…...
探索 Text-to-SQL 技术:从自然语言到数据库查询的桥梁
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、Java 与 Python 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在未来…...
Java NIO ByteBuffer 详解
什么是 ByteBuffer ByteBuffer 是 Buffer 的一个具体实现,专门用于存储和操作字节数据。它提供了高效的、基于内存的 I/O 数据处理方式。 Buffer 类是构建 Java NIO 的基础,其中 ByteBuffer 类是 Buffer 子类中最受欢迎的。这是因为字节类型是最通用的…...
【机器学习】简单线性回归算法及代码实现
线性回归算法 一、摘要二、线性回归算法概述三、损失函数的定义和衡量标准四、简单线性回归的求解和应用五、机器学习算法一般求解思路 一、摘要 本文讲解了线性回归算法的基础知识和应用,强调线性回归主要用于解决回归问题。通过分析房产价格与房屋面积的关系&…...
【前端开发】query参数和params参数的区别
在Web开发中,query参数(URL查询参数)和params参数(路由参数)是两种不同的URL传参方式,它们的核心区别如下: 一、 位置不同 query参数params参数位置URL中?之后,用&连接多个参数…...
人工智能数学基础学习PPT
学习视频:人工智能 -数学基础 文章目录 1.简介1.函数2.极限3.无穷小与无穷大4.连续性与导数5.偏导数6.方向导数7.梯度 2.微积分1.微积分基本想法2.微积分的解释3.定积分4.定积分性质5.牛顿-莱布尼茨公式 3.泰勒公式与拉格朗日1.泰勒公式2.一点一世界3.阶数的作用4.…...
企业文件防泄密软件哪个好?
在企业文件防泄密软件领域,天锐绿盾和中科数安都是备受认可的品牌,它们各自具有独特的特点和优势。 以下是对这两款软件的详细比较: 天锐绿盾 功能特点 集成性强:集成了文件加密、数据泄露防护DLP、终端安全管理、行为审计等数据安…...
美丽 百褶裙提示词 + MD
MD 参考教程:Marvelous Designer零基础教学,MD布料制作-百褶裙建模制作,次世代教学_哔哩哔哩_bilibili 【MD新手教程】30分钟教会你制作百褶裙,Marvelous Designer超简单入门案例教程_哔哩哔哩_bilibili 【c4d技术解析】MD百褶裙…...
解释和对比“application/octet-stream“与“application/x-protobuf“
介绍 在现代 Web 和分布式系统的开发中,数据的传输和交换格式扮演着关键角色。为了确保数据在不同系统之间的传输过程中保持一致性,MIME 类型(Multipurpose Internet Mail Extensions)被广泛应用于描述数据的格式和内容类型。在 …...
基于YALMIP和cplex工具箱的微电网最优调度算法matlab仿真
目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 系统建模 4.2 YALMIP工具箱 4.3 CPLEX工具箱 5.完整工程文件 1.课题概述 基于YALMIP和cplex工具箱的微电网最优调度算法matlab仿真。通过YALMIP和cplex这两个工具箱,完成微电网的最优调…...
AI前端开发技能提升与ScriptEcho:拥抱AI时代的前端开发新范式
随着人工智能技术的飞速发展,AI前端开发岗位对技能的要求也水涨船高。越来越多的企业需要具备AI相关知识和高级前端开发能力的工程师,这使得传统的前端开发模式面临着巨大的挑战。如何提升开发效率,降低人力成本,成为了摆在所有前…...
LeetCode题解:2690. 无穷方法对象,Proxy
Problem: 2690. 无穷方法对象 思路 这个问题的核心在于创建一个对象,该对象能够响应对其任何方法的调用,并返回调用的方法名称。为了实现这一点,我们可以利用 JavaScript 中的 Proxy 对象。Proxy 对象允许我们自定义对象的基本操作ÿ…...
Python中的HTTP客户端库:httpx与request | python小知识
Python中的HTTP客户端库:httpx与request | python小知识 在Python中,发送HTTP请求和处理响应是网络编程的基础。requests和httpx是两个常用的HTTP库,它们都提供了简洁易用的API来发送HTTP请求。然而,httpx作为新一代的HTTP客户端…...
RabbitMQ使用guest登录提示:User can only log in via localhost
guest用户默认是无法使用远程访问的,生产环境建议直接在对应服务器登录使用。 1、通过创建新增用户并赋予权限实现远程登录 添加新用户 rabbitmqctl add_user zjp zjp 设置管理员 rabbitmqctl set_user_tags zjp administrator 设置新用户的权限 rabbitmqctl…...
#渗透测试#批量漏洞挖掘#Crocus系统—Download 文件读取
免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…...
基于Matlab实现六自由度机械臂正逆运动仿真(源码)
在机器人技术领域,六自由度机械臂是一种广泛应用的设备,它可以实现空间中的位置和姿态控制。本项目聚焦于六自由度机械臂的正逆运动学仿真,利用MATLAB2016b作为开发工具,旨在深入理解并掌握机械臂的工作原理和运动控制。 正运动学…...
亚信安全正式接入DeepSeek
亚信安全致力于“数据驱动、AI原生”战略,早在2024年5月,推出了“信立方”安全大模型、安全MaaS平台和一系列安全智能体,为网络安全运营、网络安全检测提供AI技术能力。自2024年12月DeepSeek-V3发布以来,亚信安全人工智能实验室利…...
Django 创建第一个项目
Django 创建第一个项目 引言 Django 是一个高级的 Python Web 框架,它鼓励快速开发和干净、实用的设计。本指南将带您从头开始创建一个简单的 Django 项目,以便您能够熟悉 Django 的基本结构和概念。 准备工作 在开始之前,请确保您已经安装了 Python 和 Django。以下是安…...
RL基础概念
RL意味着模型从真实世界中获取反馈,根据策略调整参数,以达到最大化反馈的优化算法; 强化学习的核心在于:1.试错(因为仅凭reward无法得到明确的优化方向,所以需要不断多尝试);2.延迟奖…...
像取快递一样取文件?
看到一个很有意思的项目,像我们做软件分享的感觉会有用,就是现在服务器费用太贵了,如果自建的话感觉不是很值得。 FileCodeBox FileCodeBox 是一个轻量级的文件分享系统,它基于匿名口令分享文本和文件,无需注册登录&…...
Jenkins 新建配置Pipeline任务 三
Jenkins 新建配置Pipeline任务 三 一. 登录 Jenkins 网页输入 http://localhost:8080 输入账号、密码登录 一个没有创建任务的空 Jenkins 二. 创建 任务 图 NewItem 界面左上角 New Item 图NewItemSelect 1.Enter an item name:输入任务名 2.Select an ite…...
React 前端框架搭建与解析
React 前端框架搭建与解析 一、 概述 React 是 Facebook 开源的用于构建用户界面的 JavaScript 库,以其组件化、声明式编程范式以及高效的虚拟 DOM 渲染机制,成为当今最流行的前端框架之一。本文将带领你从零开始搭建一个 React 开发环境,并深入解析其核心概念。 二、 环…...
像指针操作、像函数操作的类
像指针一样的类。把一个类设计成像一个指针。什么操作符运用到指针上? 使用标准库的时候,里面有个很重要的东西叫容器。容器本身一定带着迭代器。迭代器作为另外一种智能指针。迭代器指向容器里的一个元素。迭代器用来遍历容器。 _list_iterator是链表迭…...
15.Python网络编程:进程池、进程间通信、多线程、进程和线程区别、网络通信、端口、IP地址、socket、UDP、TCP、http
1. 进程池(Process Pool) 进程池是通过将多个进程放入池中管理来避免频繁地创建和销毁进程,提高效率。Python 提供了 multiprocessing.Pool 类来实现进程池,它可以用于并行计算任务。 示例:使用进程池 from multipr…...
Ubuntu启动geteck/jetlinks实战:Docker启动
参考: JetLinks 物联网基础平台 安装Docker Ubuntu下载安装Docker-Desktop-CSDN博客 sudo apt install -y docker-compose 下载源码 git clone https://github.com/jetlinks/jetlinks-community.git cd jetlinks-community 启动 cd docker/…...
Newton 差商插值多项式
Newton 差商插值多项式 根据差商定义,把 x x x 看成[ a , b ] a,b] a,b]上一点,可得 f ( x ) f ( x 0 ) f [ x , x 0 ] ( x − x 0 ) f(x)f(x_0)f[x,x_0](x-x_0) f(x)f(x0)f[x,x0](x−x0) f [ x , x 0 ] f [ x 0 , x 1 ] f [ x , x 0 , x 1…...
ubuntu下ollama/vllm两种方式在本地部署Deepseek-R1
1.前言 今年过年,deepseek一下子爆火,导致我前段时间好好用的官网直接挤爆了,一直转圈圈到没心思过了,天天挂热搜,直接导致我的科研工作受阻(dog),好吧,话不多说,看看怎么在本地部署deepseek丝滑享受以及白嫖一下api体验>_<! 部署环境: 系统:ubuntu22.04 显…...
如何使用ps批量去除固定位置水印
使用 Photoshop 批量去除固定位置的水印,有几种方法可以实现自动化,具体取决于水印的复杂程度和你对 Photoshop 的熟悉程度: 1. 动作(Actions) 批处理(Batch): 这是最常用的方法&…...
基于 STM32 的病房监控系统
标题:基于 STM32 的病房监控系统 内容:1.摘要 基于 STM32 的病房监控系统摘要:本系统采用 STM32 微控制器作为核心,通过传感器实时监测病房内的环境参数,如温度、湿度、光照等,并将数据上传至云端服务器。医护人员可以通过手机或…...
Windows部署deepseek-r1
安装Ollama 访问Ollama下载页,选择对应的操作系统进行下载 运行OllamaSetup,进行安装 任务栏出现Ollama图标,运行正常 cmd查看Ollama版本 C:\Users\PC>ollama -v ollama version is 0.5.7 部署模型 deepseek 可访问deepseek模型页,切…...
CCFCSP第34次认证第一题——矩阵重塑(其一)
第34次认证第一题——矩阵重塑(其一) 官网链接 时间限制: 1.0 秒 空间限制: 512 MiB 相关文件: 题目目录(样例文件) 题目背景 矩阵(二维)的重塑(reshap…...
webpack打包优化策略
1. 减少打包体积 减少打包文件的大小是为了提高加载速度,降低网络带宽消耗,提升用户体验。常见的减少打包体积的优化策略包括: 代码分割(Code Splitting):将代码拆分成多个小文件,让浏览器按需…...
八股文-2025-02-12
BFC BFC属于普通流。BFC全称是Block Formatting Context,意思就是块级格式化上下文。你可以把BFC看做元素的一个属性,当元素拥有BFC属性,这个元素就可以看作是隔离了的独立容器,容器里边的元素不会影响到容器外部的元素.https://b…...
部门管理(体验,最原始方法来做,Django+mysql)
本人初学,写完代码在此记录和复盘 在创建和注册完APP之后(我的命名是employees),编写models.py文件创建表 手动插入了几条数据 1.部门查询 urls.py和views.py在编写之前,都要注意导入对应的库 urls.py:…...
联想拯救者Y9000银河麒麟系统安装Nvidia 4060显卡驱动
查了好多资料, 发现银河麒麟的资料较少, 只能自己试验了, 如有帮助, 点个赞吧~~ 前提: 本人笔记本是联想拯救者Y9000, 独立显卡 Nvidia4060, 主机系统是银河麒麟V10 (2403), 笔记本处于联网状态ÿ…...
深入解析 STM32 GPIO:结构、配置与应用实践
理解 GPIO 的工作原理和配置方法是掌握 STM32 开发的基础,后续的外设(如定时器、ADC、通信接口)都依赖于 GPIO 的正确配置。 目录 一、GPIO 的基本概念 二、GPIO 的主要功能 三、GPIO 的内部结构 四、GPIO 的工作模式 1. 输入模式 2. 输…...
突破数据壁垒,动态住宅代理IP在数据采集中的高效应用
在当今数字化时代,数据已经成为企业和个人决策的重要依据。无论是市场调研、竞争分析,还是价格监控、SEO优化,数据采集都扮演着至关重要的角色。然而,随着技术发展与网络安全措施的日益严格,传统的数据采集方式面临着前…...