当前位置: 首页 > news >正文

泛型详解.

1 泛型的引入
问题:我们之前实现过的顺序表,只能保存 int 类型的元素,如果现在需要保存 指向 Person 类型对象的引用的顺序表,请问应该如何解决?如果又需要保存指向 Book 对象类型的引用呢?

之前写的顺序表代码示例:

import java.util.Arrays;public class MyArrayList {private int[] elem;private int usedSize;private static int capacity = 10;public MyArrayList() {this.elem = new int[capacity];}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, int data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(int toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(int toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public int getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(int toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(0, 1);myArrayList.add(1, 2);myArrayList.add(2, 3);myArrayList.add(3, 4);System.out.println(myArrayList.size());myArrayList.display();System.out.println(myArrayList.contains(3));System.out.println(myArrayList.contains(2));System.out.println(myArrayList.search(5));System.out.println(myArrayList.search(2));System.out.println(myArrayList.getPos(0));System.out.println(myArrayList.usedSize);myArrayList.display();myArrayList.remove(1);myArrayList.remove(2);myArrayList.display();myArrayList.remove(4);myArrayList.display();myArrayList.clear();System.out.println("==============");myArrayList.display();}
}
  • 首先,我们在学习多态过程中已知一个前提,父类的引用可以指向子类的对象。
  • 其次,我们也已知 Object 是 java 中所有类的祖先类
     

那么,要解决上述问题,我们很自然的想到一个解决办法,将我们的顺序表的元素类型定义成 Object 类型,这样我们的 Object 类型的引用可以指向 Person 类型的对象或者指向 Book 类型的对象了。

因为代码改动较多,现在指出主要代码:

这样,我们可以就可以很自由的存储指向任意类型对象的引用到我们的顺序表了。
 

改编后的代码: 

 

package test1;import java.util.Arrays;public class MyArrayList {private Object[] elem;private int usedSize;private static int capacity = 10;public MyArrayList() {this.elem = new Object[capacity];}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, Object data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");System.out.println();}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(Object toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(Object toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public Object getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(int toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList books = new MyArrayList();for (int i = 0; i < 10; i++) {books.add(i,new Book("三国演义", "罗贯中", 15));}books.display();
//        MyArrayList myArrayList = new MyArrayList();
//        myArrayList.add(0, 1);
//        myArrayList.add(1, 2);
//        myArrayList.add(2, 3);
//        myArrayList.add(3, 4);
//        System.out.println(myArrayList.size());
//        myArrayList.display();
//        System.out.println(myArrayList.contains(3));
//        System.out.println(myArrayList.contains(2));
//        System.out.println(myArrayList.search(5));
//        System.out.println(myArrayList.search(2));
//        System.out.println(myArrayList.getPos(0));
//        System.out.println(myArrayList.usedSize);
//        myArrayList.display();
//        myArrayList.remove(1);
//        myArrayList.remove(2);
//        myArrayList.display();
//        myArrayList.remove(4);
//        myArrayList.display();
//        myArrayList.clear();
//        System.out.println("==============");
//        myArrayList.display();}
}


遗留问题:现在的 MyArrayList 虽然可以做到添加任意类型的引用到其中了,但遇到以下代码就会产生问题。

写一个Person类:

 接下来我称之为牛马操作:

编译竟然正确,没有报红,我们运行一下看看:

 

运行时会抛出了异常
 

提示:问题暴露的越早,影响越小。编译期间的问题只会让开发者感觉到,运行期间的错误会让所有的软件使用者承受错误风险。

所以我们需要一种机制,可以 1. 增加编译期间的类型检查 2. 取消类型转换的使用 泛型就此诞生!
 

2.泛型的分类

  • 1. 泛型类
  • 2. 泛型方法

3 泛型类的定义的简单演示


 注意: 泛型类可以一次有多个类型变量,用逗号分割。
 

4 泛型背后作用时期和背后的简单原理

  • 1. 泛型是作用在编译期间的一种机制,即运行期间没有泛型的概念。
  • 2. 泛型代码在运行期间,就是我们上面提到的,利用 Object 达到的效果(这里不是很准确,以后会做说明)。
     

5 泛型类的使用


 

通过以上代码,我们可以看到泛型类的一个使用方式:只需要在所有类型后边跟尖括号,并且尖括号内是真正的类型,即 E 可以看作的最后的类型。
 

看具体代码:

package test1;import java.util.Arrays;public class MyArrayList<E> {private Object[] elem;private int usedSize;private static int capacity = 10;private E e;public MyArrayList() {this.elem = new Object[capacity];this.e = e;}public boolean isFull() {if (this.usedSize == capacity) {return true;}return false;}public void add(int pos, E data) {if (pos < 0 || pos > this.usedSize) {System.out.println("pos位置不合法");return;}if (isFull()) {this.elem = Arrays.copyOf(this.elem, 2 * capacity);capacity *= 2;}for (int i = this.usedSize - 1; i >= pos; i--) {this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");System.out.println();}System.out.println();}public boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}public boolean contains(E toFind) {if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}public int search(E toFind) {if (isEmpty()) {return -1;}for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}public Object getPos(int pos) {if (isEmpty()) {throw new RuntimeException("顺序表为空!");}if (pos < 0 || pos >= this.usedSize) {throw new RuntimeException("pos不合法");}return this.elem[pos];}public int size() {return this.usedSize;}public void setPos(int pos, int value) {if (pos < 0 || pos >= this.usedSize) {System.out.println("pos位置不合法!");return;}this.elem[pos] = value;}public void remove(E toRemove) {if (isEmpty()) {return;}int index = search(toRemove);if (index == -1) {System.out.println("没有你要删除的数字!");}for (int i = index; i < this.usedSize - 1; i++) {this.elem[i] = this.elem[i + 1];}this.usedSize--;}public void clear() {for (int i = 0; i < this.usedSize; i++) {this.elem[i] = 0;}this.usedSize = 0;}public static void main(String[] args) {MyArrayList<Book> books = new MyArrayList<Book>();books.add(0, new Book("红楼梦", "曹雪芹", 18));books.add(2, new Person("lisi", "lll"));//        Book book1 = new Book("红楼梦", "曹雪芹", 18);
//        for (int i = 0; i < 10; i++) {
//            if (i == 0) {
//                books.add(i, book1);
//            } else {
//                books.add(i, new Book("三国演义", "罗贯中", 15));
//            }
//        }
//        books.display();
//        Person person = (Person) books.getPos(0);
//        MyArrayList myArrayList = new MyArrayList();
//        myArrayList.add(0, 1);
//        myArrayList.add(1, 2);
//        myArrayList.add(2, 3);
//        myArrayList.add(3, 4);
//        System.out.println(myArrayList.size());
//        myArrayList.display();
//        System.out.println(myArrayList.contains(3));
//        System.out.println(myArrayList.contains(2));
//        System.out.println(myArrayList.search(5));
//        System.out.println(myArrayList.search(2));
//        System.out.println(myArrayList.getPos(0));
//        System.out.println(myArrayList.usedSize);
//        myArrayList.display();
//        myArrayList.remove(1);
//        myArrayList.remove(2);
//        myArrayList.display();
//        myArrayList.remove(4);
//        myArrayList.display();
//        myArrayList.clear();
//        System.out.println("==============");
//        myArrayList.display();}
}

 

那么现在就会出现编译错误 ,这就是泛型的作用!

注意: Book 只能想象成 E 的类型,但实际上 E 的类型还是 Object。
 

6 泛型总结

  • 1. 泛型是为了解决某些容器、算法等代码的通用性而引入,并且能在编译期间做类型检查。
  • 2. 泛型利用的是 Object 是所有类的祖先类,并且父类的引用可以指向子类对象的特定而工作。
  • 3. 泛型是一种编译期间的机制,即 MyArrayList<Person> 和 MyArrayList<Book> 在运行期间是一个类型。
  • 4. 泛型是 java 中的一种合法语法,标志就是尖括号 <>
     

相关文章:

泛型详解.

1 泛型的引入 问题&#xff1a;我们之前实现过的顺序表&#xff0c;只能保存 int 类型的元素&#xff0c;如果现在需要保存 指向 Person 类型对象的引用的顺序表&#xff0c;请问应该如何解决&#xff1f;如果又需要保存指向 Book 对象类型的引用呢&#xff1f; 之前写的顺序表…...

Vue 3.0 响应性 深入响应性原理 【Vue3 从零开始】

现在是时候深入了&#xff01;Vue 最独特的特性之一&#xff0c;是其非侵入性的响应性系统。数据模型是被代理的 JavaScript 对象。而当你修改它们时&#xff0c;视图会进行更新。这让状态管理非常简单直观&#xff0c;不过理解其工作原理同样重要&#xff0c;这样你可以避开一…...

升级 vue3 常见问题总汇

Ⅰ、前言 虽然 vue3 是没有删除 vue2 的 选项式 API &#xff0c; 但是我们升级vue3 还是需要修改很多问题的下面来看看我们升级常见的一些问题 &#x1f447; 文章目录Ⅰ、前言Ⅱ、解决兼容问题1、路由的创建方式2、路由的方法变化3、升级 vuex 到 4.x4、作用域 插槽语法修改…...

汽车 Automotive > T-BOX GNSS高精定位测试相关知识

参考&#xff1a;https://en.wikipedia.org/wiki/Global_Positioning_SystemGPS和GNSS的关系GPS&#xff08;Global Positioning System&#xff09;&#xff0c;全球定位系统是美国军民两用的导航定位卫星系统&#xff0c;GPS包含双频信号&#xff0c;频点L1、L2和L5GNSS&…...

大数据面试核心101问【大厂超级喜欢这些题】

之前出过《史上最全的大数据开发八股文》这篇文章&#xff0c;同学们都觉得还不错&#xff0c;但是有些同学觉得那个背起来还是有些吃力&#xff0c;于是我再次回顾了自己之前面试所有大厂的一些面试题以及牛客上面的一些面经&#xff0c;然后总结了频率问的最高的101问&#x…...

代码随想录算法训练营第四十八天 | leetcode 121. 买卖股票的最佳时机,122.买卖股票的最佳时机II

代码随想录算法训练营第四十八天 | leetcode 121. 买卖股票的最佳时机&#xff0c;122.买卖股票的最佳时机II121. 买卖股票的最佳时机122.买卖股票的最佳时机II121. 买卖股票的最佳时机 题目&#xff1a; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支…...

RAD 11.3 delphi和C++改进后新增、废弃及优化的功能

RAD 11.3 delphi和C改进后新增和废弃的功能 目录 RAD 11.3 delphi和C改进后新增和废弃的功能 一、版本RAD 11.3 delphi和C改进后新增功能 1、官方视频位置&#xff1a; 2、官方文档的链接位置&#xff1a; 二、版本RAD 11.3 delphi和C改进后废弃的功能 2.1、编译器不再使…...

【C++】引用

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、引用1.1 引用概念1.2 引用特性…...

LPNet for Image Derain

Lightweight Pyramid Networks for Image Deraining前置知识高斯-拉普拉斯金字塔图像中的高频信息和低频信息为什么高斯-拉普拉斯金字塔可以实现去雨&#xff1f;可能性分析网络结构整体结构&#xff1a;子网结构&#xff1a;递归块结构&#xff1a;后续补充代码 前置知识 这…...

【NLP相关】基于现有的预训练模型使用领域语料二次预训练

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

使用git进行项目管理--git使用及其常用命令

使用git进行项目管理 文章目录 使用git进行项目管理git使用1.添加用户名字2.添加用户邮箱3.git初始化4.add5.commit6.添加到gitee仓库7.推送到gitee8.切换版本git常用命令git add把指定的文件添加到暂存区中添加所有修改、已删除的文件到暂存区中添加所有修改、已删除、新增的文…...

Mybatis_CRUD使用

目录1 Mybatis简介环境说明:预备知识:1.1 定义1.2 持久化为什么需要持久化服务呢&#xff1f;1.3 持久层1.4 为什么需要Mybatis2 依赖配置3 CRUDnamespaceselect &#xff08;查询用户数据&#xff09;※传值方式&#xff1a;于方法中传值使用Map传值insert &#xff08;插入用…...

JVM的过程内分析和过程间分析有什么区别?

问&#xff1a; 目前所有常见的Java虚拟机对过程间分析的支持都相 当有限&#xff0c;要么借助大规模的方法内联来打通方法间的隔阂&#xff0c;以过程内分析&#xff08;Intra-Procedural Analysis&#xff0c; 只考虑过程内部语句&#xff0c;不考虑过程调用的分析&#xff…...

LearnDash测验报告如何帮助改进您的课程

某一个场景。Pennywell 大学有一门课程“Introduction to Linear Algebra”。上学期进行了两次测验。20% 的学生在第一次测验中不及格&#xff0c;而 80% 在第二次测验中不及格。在进一步评估中&#xff0c;观察到第一次测验不及格的学生在第二次测验中也不及格。在第二次测验中…...

如何通过Java将Word转换为PDF

Word是我们日常编辑文档内容时十分常用的一种文档格式。但相比之下&#xff0c;PDF文档的格式、布局更为固定&#xff0c;不易被更改。在保存或传输较为重要的文档内容时&#xff0c;PDF文档格式也时很多人的不二选择。很多时候我们都会遇到需要将Word转换为PDF的情况。下面我就…...

DOM型XSS

DOM型XSSDOM是什么DOM型XSSDOM型XSS实操DOM是什么 DOM就是Document。 文档是由节点构成的集合&#xff0c;在DOM里存在许多不同类型的节点&#xff0c;主要有&#xff1a;元素节点、文本节点&#xff0c;属性节点。 元素节点&#xff1a;好比< body >< p >< h …...

04-项目立项:项目方案、可行性分析、产品规划、立项评审

文章目录4.1 项目方案立项阶段4.2 可行性分析4.3 产品规划4.4 立项评审4.4.1 立项说明书的主要内容4.4.2 立项评审流程章节总结4.1 项目方案 学习目标&#xff1a; 能够输出产品项目方案 项目开发设计流程的主要阶段&#xff1a; 立项阶段 → 设计阶段 → 开发阶段 → 测试阶…...

数据分享|NPP VIIRS夜间灯光数据(2012-2020逐月)

2011年10月美国的“索米”国家极轨卫星伙伴卫星(Suomi National Polar-orbiting Partnership or Suomi NPP)发射,它搭载的VIIRS传感器上有一个称为DNB(Day Night Band)的波段能够在500米分辨率(比原来的OLS提高6倍)的尺度上对地表开展每天覆盖全球一次的高灵敏度(比OLS提…...

网络概论笔记

概论 网络研究的是节点和边 移动互联到物联网时代&#xff0c;只有有互联网&#xff0c;网络就不会落伍 协议&#xff1a;对等层面的实体固定的通信规则 协议包括&#xff1a;语法&#xff0c;语义&#xff0c;格式&#xff0c;次序&#xff0c;动作 网络是任意连接的 服务…...

软工2023个人作业二——软件案例分析

项目内容这个作业属于哪个课程2023年北航敏捷软件工程这个作业的要求在哪里个人作业-软件案例分析我在这个课程的目标是学习并掌握现代软件开发和项目管理技术&#xff0c;体验敏捷开发工作流程这个作业在哪个具体方面帮助我实现目标从软件工程角度分析比较我们所熟悉的软件&am…...

python数据分析表格文档Excel数据分析器统计源码

wx供重浩&#xff1a;创享软件 对话框发送&#xff1a;python表格 获取完整源码源文件说明文档可执行文件等 在PyCharm中运行《Excel数据分析师》即可进入如图1所示的系统主界面。在该界面中&#xff0c;通过顶部的工具栏可以选择所要进行的操作。 具体的操作步骤如下&#xff…...

Istio Sidecar启动顺序 - 导致的应用容器网络不通

目录一、问题二、Istio 1.7及其之后版本的解决方案2.1 方式1&#xff1a;安装Istio时全局设置2.2 方式2&#xff1a;在应用Deployment通过annotation设置2.3 holdApplicationUntilProxyStarts启用效果三、Istio 1.7之前的解决方案一、问题 线上应用集成了Spring Cloud K8S Con…...

3696. 构造有向无环图

Powered by:NEFU AB-IN Link 文章目录3696. 构造有向无环图题意思路代码3696. 构造有向无环图 题意 Codeforces Round 656 (Div. 3) E 给定一个由 n个点和 m条边构成的图。 不保证给定的图是连通的。 图中的一部分边的方向已经确定&#xff0c;你不能改变它们的方向。 剩下的边…...

RuoYi-Flowable-Plus(代码生成)

RuoYi-Flowable-Plus搭建 若依所有扩展项目的代码生成功能都是一样的&#xff0c;RuoYi-Flowable-Plus为例来演示。 模块创建 1.创建新模块ruoyi-student2.编辑RuoYi-Flowable-Plus\pom.xml <dependency><groupId>com.ruoyi</groupId><artifactId>ruoy…...

训练CV模型常用的方法与技巧

最近参加一个CV比赛&#xff0c;看到有参赛者分享了自己训练图像识别模型时常用到的小技巧&#xff0c;故对其进行记录、整理&#xff0c;方便未来继续学习。整理了很多&#xff0c;它们不一定每次有用&#xff0c;但请记在心中&#xff0c;说不定未来某个任务它们就发挥了作用…...

[Java·算法·中等]LeetCode22. 括号生成

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2分析思路3题解3&#x1f449;️ 力扣原文 题目 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 输入&#xff1a;n 3 输出&…...

Git项目合并实践

Git项目合并实践 一、前言 环境 操作系统&#xff1a;Windows 10 专业版 代码托管平台&#xff1a;Gitee 场景 同一个项目&#xff0c;在某一个时间点&#xff0c;被另外一个团队拷贝和修改&#xff0c;并且代码不在同一个仓库&#xff0c;最后需要合并项目 不是同一个项…...

C++实战md5、base64算法实现(附源码)

C++常用功能源码系列 文章目录 C++常用功能源码系列前言一、常用加密算法1. md5是什么二、源码1. md52. base64、decode总结前言 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务…...

P6专题:P6 EPPM和PPM基本概念

目录 引言 Oracles Primavera P6 Enterprise Project Portfolio Management&#xff08;P6 EPPM&#xff09; Oracles Primavera P6 Professional Project Management 引言 Oracle Primavera系列软件专注于项目密集型企业&#xff0c;其整个项目生命周期内所有项目的组合管…...

【为什么事务@Transactional会失效】

在Spring框架中&#xff0c;Transactional注解用于声明一个方法需要被包含在事务中&#xff0c;以确保数据库操作的一致性和完整性。Transactional注解通常用于Service层或DAO层的方法上。 Transactional注解失效可能是由以下原因引起的&#xff1a; 注解未被正确声明或配置&a…...