[Java基础系列第2弹]泛型:一种提高代码复用性和灵活性的技术

2023-11-13

一、什么是泛型?

        泛型(Generics)是一种编程技术,它可以让我们在定义类、接口或方法时,使用一个或多个类型参数(Type Parameter),而不是具体的类型。这样,我们就可以在实例化或调用时,根据需要指定具体的类型,从而实现代码的复用性和灵活性。

        例如,我们可以定义一个泛型类List<T>,它表示一个元素类型为T的列表。T是一个类型参数,它可以是任何类型。当我们创建一个List对象时,我们可以指定T的具体类型,比如List<String>表示一个字符串列表,List<Integer>表示一个整数列表,等等。

二、为什么要使用泛型?

泛型有以下几个优点:

  • 提高代码的复用性。我们可以用同一个泛型类或方法来处理不同类型的数据,而不需要为每种类型都写一个专门的类或方法。
  • 提高代码的安全性。我们可以在编译时检查类型的匹配,避免在运行时出现类型转换错误。
  • 提高代码的可读性。我们可以用有意义的类型参数来表示数据的特征,而不是用通用的Object或其他基类。

三、如何使用泛型?

要使用泛型,我们需要遵循以下几个步骤:

  • 定义泛型类、接口或方法。我们需要在类、接口或方法名后面加上一对尖括号(<>),并在其中写上一个或多个类型参数。例如:
public class List<T> {
  // 类体
}

public interface Comparable<T> {
  // 接口体
}

public static <T> void sort(T[] array) {
  // 方法体
}
  • 实例化泛型类或调用泛型方法。我们需要在创建对象或调用方法时,指定类型参数的具体类型。例如:
List<String> names = new List<>(); // 创建一个字符串列表
names.add("Alice");
names.add("Bob");

Comparable<Integer> c = new Comparable<>() { // 创建一个整数比较器
  @Override
  public int compareTo(Integer o) {
    return this - o;
  }
};

Integer[] numbers = {3, 1, 4, 2};
sort(numbers); // 调用泛型方法排序
  • 使用泛型类、接口或方法。我们可以像使用普通的类、接口或方法一样,使用泛型类、接口或方法。只是在使用类型参数时,要注意它们的范围和限制。例如:
public class List<T> {
  private T[] elements; // 使用类型参数作为数组元素类型
  private int size;

  public List() {
    elements = (T[]) new Object[10]; // 创建一个Object数组并强制转换为T数组
    size = 0;
  }

  public void add(T element) {
    if (size == elements.length) {
      resize(); // 扩容
    }
    elements[size++] = element; // 添加元素
  }

  public T get(int index) {
    if (index < 0 || index >= size) {
      throw new IndexOutOfBoundsException(); // 抛出异常
    }
    return elements[index]; // 返回元素
  }

  private void resize() {
    T[] newElements = (T[]) new Object[elements.length * 2]; // 创建一个新数组并强制转换为T数组
    System.arraycopy(elements, 0, newElements, 0, size); // 复制原数组元素到新数组
    elements = newElements; // 更新引用
  }
}

四、泛型的高级特性

除了基本的使用方式外,泛型还有一些高级的特性,比如:

  • 泛型继承。我们可以让一个泛型类继承另一个泛型类,或者实现一个泛型接口。例如:
public class Stack<T> extends List<T> { // 栈类继承列表类
  // 类体
}

public class Student implements Comparable<Student> { // 学生类实现比较器接口
  // 类体
}
  • 泛型限定。我们可以在定义类型参数时,指定它们的上界(Upper Bound)或下界(Lower Bound),来限制它们的取值范围。例如:
public static <T extends Number> double sum(T[] array) { // 定义一个类型参数T,它必须是Number或其子类
  double sum = 0;
  for (T t : array) {
    sum += t.doubleValue(); // 调用Number的方法
  }
  return sum;
}

public static void print(List<? super Integer> list) { // 定义一个通配符类型?,它必须是Integer或其父类
  for (Object o : list) {
    System.out.println(o); // 打印对象
  }
}
  • 泛型擦除。泛型是一种编译时的技术,它在运行时会被擦除(Erasure),也就是说,泛型类或方法在运行时会变成普通的类或方法,类型参数会被替换为它们的上界或Object。这样做的目的是为了保持与旧版本的Java代码的兼容性。

但是,这也带来了一些限制,比如:

  • 我们不能使用instanceofnew操作符来操作泛型类型。
  • 我们不能使用基本类型作为类型参数。
  • 我们不能在静态域或方法中使用类型参数。
  • 我们不能直接获取泛型类型的Class对象。

五、总结

泛型是一种提高代码复用性和灵活性的技术,它可以让我们在定义类、接口或方法时,使用类型参数来代替具体的类型,从而实现代码的通用性和可扩展性。泛型还有一些高级的特性,比如泛型继承、泛型限定和泛型擦除,它们可以让我们更灵活地使用泛型。


这里是热爱编程的小高,希望和大家共同进步~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Java基础系列第2弹]泛型:一种提高代码复用性和灵活性的技术 的相关文章

  • 为什么会出现此异常 FileItemStream$ItemSkippedException?

    在 gwt Web 应用程序中 我必须发送一个文件和附加的一些参数 在服务器端 try ServletFileUpload upload new ServletFileUpload FileItemIterator iterator upl
  • Android PhoneGap 插件,UI 选项卡栏,调整 WebView 大小

    我正在创建一个美味的 PhoneGap 插件 希望一旦它能被打开 准备好了 插件基本完成了 我只需要一个漂亮的用户界面 相互作用 简而言之 我想创建一个 本机 android 工具栏组件 如果您实现 PhoneGap UIControls
  • Jackson - 反序列化嵌套 JSON

    我有一个 JSON 字符串 其格式如下 response execution status ready report cache hit true created on 2013 07 29 08 42 42 fact cache erro
  • jvm 次要版本与编译器次要版本

    当运行使用具有相同主要版本但次要版本高于 JVM 的 JDK 编译的类时 JVM 会抛出异常吗 JDK 版本并不重要 类文件格式版本 http blogs oracle com darcy entry source target class
  • 防止 Spring Boot 注册 Spring Security 过滤器之一

    我想禁用安全链中的 Spring Security 过滤器之一 我已经看到了防止 Spring Boot 注册 servlet 过滤器 https stackoverflow com questions 28421966 prevent s
  • 使用 Java 在 WebDriver 中按 Ctrl+F5 刷新浏览器

    我已经使用 java 刷新了 WebDriver 中的浏览器 代码如下 driver navigate refresh 如何使用 Java 在 WebDriver 中按 Ctrl F5 来做到这一点 我认为您可以使用 WebDriver 和
  • URL.setURLStreamHandlerFactory

    我正在使用带有嵌入式 Jetty 的可执行 jar 开发一个 Web 应用程序 我的jar包含一个依赖jar jar in jar 我参考了JarRsrcLoader and RsrcURLStreamHandlerFactory由 Ecl
  • 无法使用 json 架构验证器根据预定义的 yaml 文件验证查询参数

    我需要根据预定义的 yaml 文件架构验证查询参数的架构 因此我使用 json 架构验证器 验证如何失败 我正在执行以下步骤 填充参数和相应的架构 final List
  • 使用 ChannelExec 的命令未执行 - Jsch

    我正在使用 Jsch 在服务器中创建一个文件并执行一些命令 对于文件创建 它工作正常 但是对于命令执行 则不然 它保持状态 1 仍在处理它 并永远保持该状态 这种情况发生在 shell 执行或我尝试成为 root 时 请按照以下方法操作 p
  • java.lang.LinkageError:尝试重复的类定义

    为什么会发生错误以及如何修复它 02 13 02 pool 4 thread 2 WARN Exception in thread pool 4 thread 2 02 13 02 pool 4 thread 2 WARN java lan
  • 字符串池可以包含两个具有相同值的字符串吗? [复制]

    这个问题在这里已经有答案了 字符串池可以包含两个具有相同值的字符串吗 String str abc String str1 new String abc Will the second statement with new operator
  • Java Microsoft Excel API [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • JFace ColumnWeigthData 导致父级增长

    我有一个 Eclipse RCP 应用程序 并且想要在TableViewer using ColumnWeigthData as ColumnLayoutData 问题是父表单 ScrolledForm在示例代码中 每当我布局表格时都会增加
  • 如何导入 org.apache.commons.lang3.ArrayUtils;进入 Eclipse [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我如何导入 org apache commons lang3 ArrayUtils 将库添加到 Ecl
  • 异步迭代器

    我有以下代码 while slowIterator hasNext performLengthTask slowIterator next 由于迭代器和任务都很慢 因此将它们放入单独的线程中是有意义的 这是对迭代器包装器的快速而肮脏的尝试
  • 发生错误。请参阅日志文件 - eclipse juno

    每当我启动 Eclipse Juno 时 都会出现错误 发生错误 请查看日志文件 C Program Files eclipse configuration 1362989254411 log 有的网站说卸载jdk重新安装 我这样做了 但没
  • 创建正则表达式匹配数组

    在Java中 我试图将所有正则表达式匹配返回到一个数组 但似乎您只能检查模式是否匹配某些内容 布尔值 如何使用正则表达式匹配来形成与给定字符串中的正则表达式匹配的所有字符串的数组 4城堡的回答 https stackoverflow com
  • JavaFX - 为什么多次将节点添加到窗格或不同的窗格会导致错误?

    我现在正在学习基本的 JavaFX 我不明白我正在阅读的书中的这一说法 不 诸如文本字段之类的节点只能添加到一个窗格中一次 将节点添加到多次窗格或不同的窗格将导致运行时错误 我可以从书中提供的UML图看出它是一个组合 但我不明白为什么 库类
  • 如何解决 PDFBox 没有 unicode 映射错误?

    我有一个现有的 PDF 文件 我想使用 python 脚本将其转换为 Excel 文件 目前正在使用PDFBox 但是存在多个类似以下错误 org apache pdfbox pdmodel font PDType0Font toUnico
  • Java:使用 Graph API 在线更新 Sharepoint 上的 docx 文件

    我在使用 Java 在线更新 Sharepoint 上的 docx 文件时遇到问题 首先 我检查了构建 PUT 请求的 URL 此处 并使用此请求 PUT drives drive id items item id content 我首先使

随机推荐

  • 如何在Android应用中使用百度地图api

    本篇通过一个简单的示例一步步介绍如何在Android应用中使用百度地图api 1 下载百度地图移动版API Android 开发包 要在Android应用中使用百度地图API 就需要在工程中引用百度地图API开发包 这个开发包包含两个文件
  • 互联网行业为什么能吸引越来越多的年轻人?尤其是程序员……

    上周发的关于全国程序员4月的薪资依旧稳步上涨的推文 着实让羡慕了一把 虽然互联网大厂屡次传来裁员的消息 但依然阻挡不了年轻人向互联网行业涌入的决心 那么 问题来了 互联网行业为什么能吸引越来越多的年轻人 弹性上班 很多互联网公司都会有弹性上
  • linux xargs命令使用

    linux xargs命令使用 基本的命令是 command xargs I 选项 格式 xargs I rep str comand rep srt 其中rep str 为代替传递给xargs参数 可以使 等符号 其主要作用是当xargs
  • jquery获取一组radio被选中项的值

    相关文章 EXT使用中IE下的DOCTYPE问题 DOJO的菜单老出问题 IE6 IE7和Firefox对Div处理的差异 推荐圈子 EXT 更多相关推荐
  • 在Vi里面实现字符串的批量替换

    在Vi里面实现字符串的批量替换 在Vi里面实现字符串的批量替换 a 文件内全部替换 s abc def g 用def替换文件中所有的abc 例如把一个文本文件里面的 linuxidc com 全部替换成 linuxidc net s lin
  • 训练DPT:由测试test到训练train图像的一个epochs的optimize.zero_grad() loss.backward() optimizer.step()

    不知道大家有没有这样的感受 很多研究型论文通常会给出他们的test py文件 但是其train py文件往往是空白的 这时候感觉文章的test确实很nice 就想去探究其更原始 最优参数 训练出的参数过程 那么这里就不得不开始研究如何从te
  • ssm整合无法注入dao层

    spring整合mybatis 在部署项目时 一直报错 dao无法注入ioc容器 Error creating bean with name accountController Unsatisfied dependency expresse
  • 听说CentOS 8 已经成绝版了 ?难道就没有后续了么?很烦!

    一 CentOS 8 已是绝版 CentOS Stream 才是未来 CentOS 官方发文称 CentOS Stream 才是 CentOS 项目的未来 在接下来的一年里 将逐步把开发工作的重心从 CentOS Linux 往 CentO
  • Linux设置用户的密码有效期

    使用命令chage加参数可以查看 更改用户密码的有效期 1 查看用户密码有效期 chage l username 如下是永不会过期的类型 以下是90天有效期的类型 2 修改密码到期时间 通过参数 M 设置账户密码的到期时间 语法 chage
  • Lua里实现将table转成字符串(序列化)和将字符串转换回table(反序列化)

    file name table序列化和反序列化的问题 lua author Clark 陈泽丹 created 2011 12 22 备注 支持table的递归结构 但数据类型不支持function属性 因为function只是记录地址 在
  • 《GPU的革命》文章整理

    整理几年前写的文章 或许对初学CUDA编程的朋友有帮助 CUDA 线程执行模型分析 一 招兵 GPU的革命 CUDA 线程执行模型分析 二 大军未动粮草先行 GPU的革命 CUDA硬件实现分析 一 安营扎寨 GPU的革命 CUDA硬件实现分
  • 16个自动化测试面试问题与解答

    1 什么是自动化测试 自动化测试是一种使用自动化工具编写和执行测试人员测试脚本和案例的技术 自动化测试的主要目标是减少手动运行的测试用例数量 而不是完全取消手动测试 2 什么时候自动化测试 在以下情况下首选自动化 重复性任务 烟雾和理智测试
  • vue3项目修改浏览器的项目icon小图标

    修改vue3项目的浏览器的图标 vue2修改图标
  • AD每次更新PCB元器件位置会变动

    用AD画板 在重新更新元器件标识注视后 更新PCB后会出现某些器件移到了外面 把它摆放好以后 如果又对原理图中进行了改动 在更新PCB之后 刚才摆放好的元器件就又移到外面 另外 其它一些情况也会出现更新PCB位置变动的情况 下面是解决办法
  • 【matplotlib】可视化解决方案——如何向图表中添加数据表

    概述 虽然 matplotlib 主要用途是绘图 但是他还是可以在绘图时帮助我们做一些其他事务 比如在图表旁边放置一个整齐的数据表格 我们必须明白为数据绘制可视化图形主主要是是为了解释那些不能理解的数据 将一些来自数据整体集合的总结性或者突
  • Pytest框架:测试用例setup和teardown

    背景 假如我们进入多个模块前 每个模块有一个用例 都要打开浏览器登录 执行完毕后 需要退出再关闭浏览器 即每次运行前都要执行登录打开 退出关闭两个大量重复的操作 这些我们都可以用前置后置初始化环境去实现 怎么去实现 就是下面要介绍的 用例设
  • 【上新】手工制作马赛克瓷砖,为 Gotchiverse 添色彩!

    你无需成为艺术家即可帮助一起绘制 Gotchiverse 现在 每个人都可以用马赛克瓷砖让他们的创造力得到发挥 让我们在 Gotchiverse 中涂抹色彩吧 最新和最伟大的美学 NFT 已准备好冲击 Gotchiverse 了 介绍一下马
  • 显示this application has requested the runtime to terminate it in an unusual way.问题的简单分析

    运行程序是出现了this application has requested the runtime to terminate it in an unusual way 的异常报告 有些Win7的操作系统可能会出现此类问题 一般是软件运行时
  • LeetCode第45题解析

    给定一个非负整数数组 你最初位于数组的第一个位置 数组中的每个元素代表你在该位置可以跳跃的最大长度 你的目标是使用最少的跳跃次数到达数组的最后一个位置 示例 输入 2 3 1 1 4 输出 2 解释 跳到最后一个位置的最小跳跃数是 2 从下
  • [Java基础系列第2弹]泛型:一种提高代码复用性和灵活性的技术

    一 什么是泛型 泛型 Generics 是一种编程技术 它可以让我们在定义类 接口或方法时 使用一个或多个类型参数 Type Parameter 而不是具体的类型 这样 我们就可以在实例化或调用时 根据需要指定具体的类型 从而实现代码的复用