【Java 基础篇】Java 泛型:类型安全的编程指南

news2024/11/28 6:36:59

在这里插入图片描述

在 Java 编程中,泛型是一项强大的特性,它允许您编写更通用、更安全和更灵活的代码。无论您是初学者还是有经验的 Java 开发人员,了解和掌握泛型都是非常重要的。本篇博客将从基础概念一直深入到高级应用,详细介绍 Java 泛型。

什么是泛型?

泛型是 Java 编程语言的一项特性,用于实现通用性更强的类、接口和方法。它允许您编写一次代码,然后可以用于多种数据类型,而不需要为每种数据类型都编写不同的代码。泛型的核心思想是参数化类型,即在定义类、接口或方法时,可以将类型作为参数传递。

泛型的主要优点包括:

  • 类型安全性:泛型可以在编译时捕获类型错误,而不是在运行时发生异常。这可以帮助您在编写代码时检测和修复错误,提高代码的可靠性。

  • 代码复用:泛型允许您编写通用的代码,可以适用于不同类型的数据。这样,您可以避免重复编写类似的代码。

  • 更清晰的代码:使用泛型可以使代码更易于理解和维护,因为它提供了更多的类型信息。

泛型的基本用法

泛型类

首先,让我们从泛型类开始,了解如何定义和使用泛型类。泛型类可以接受一个或多个类型参数,并在类的定义中使用这些参数。例如,下面是一个简单的泛型类 Box,用于存储任意类型的对象:

public class Box<T> {
    private T data;

    public Box(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}

在上面的示例中,Box 类接受一个类型参数 T,然后使用 T 来定义数据字段和方法。这使得 Box 类可以存储不同类型的数据。

泛型方法

除了泛型类,Java 还支持泛型方法。泛型方法是在方法中使用泛型类型参数的方法。例如,下面是一个泛型方法 printArray,用于打印数组中的元素:

public <T> void printArray(T[] array) {
    for (T item : array) {
        System.out.print(item + " ");
    }
    System.out.println();
}

在上面的示例中,<T> 表示 printArray 方法接受一个类型参数 T,然后可以在方法中使用 T 类型。

使用泛型类和方法

使用泛型类和方法非常简单。以下是一些示例:

public static void main(String[] args) {
    // 使用泛型类
    Box<Integer> intBox = new Box<>(42);
    int value = intBox.getData(); // 获取存储的整数

    // 使用泛型方法
    String[] strings = {"Hello", "World"};
    printArray(strings); // 打印字符串数组

    Integer[] integers = {1, 2, 3};
    printArray(integers); // 打印整数数组
}

在上面的示例中,我们创建了一个 Box 对象来存储整数,并使用 printArray 方法分别打印了字符串数组和整数数组。

泛型的通配符

通配符是一种用于处理未知类型的泛型的方式。Java 中有两种通配符:?? extends T。它们允许您编写能够处理不同类型的泛型代码。

通配符 ?

通配符 ? 表示未知类型,可以用于表示任意类型的泛型。通常情况下,通配符 ? 用于方法参数中,以接受各种类型的数据。例如:

public void printList(List<?> list) {
    for (Object item : list) {
        System.out.print(item + " ");
    }
    System.out.println();
}

上面的示例中,printList 方法接受一个未知类型的列表,并打印列表中的元素。这使得方法可以接受不同类型的列表。

通配符 ? extends T

通配符 ? extends T 表示类型限定,它表示通配符可以接受 T 类型或其子类型。这通常用于方法参数中,以确保只能接受指定类型及其子类型的数据。例如:

public double sumOfList(List<? extends Number> list) {
    double sum = 0.0;
    for (Number number : list) {
        sum += number.doubleValue();
    }
    return sum;
}

在上面的示例中,sumOfList 方法接受一个限定为 Number 或其子类型的列表,并计算列表中所有元素的总和。

泛型的限制和约束

在使用泛型时,有一些限制和约束需要注意:

类型擦除

Java 中的泛型是通过类型擦除来实现的。这意味着在编译时,泛型类型信息会被擦除,代码中只剩下原始类型。这可以带来一些限制,例如不能创建泛型数组和无法获得泛型的实际类型参数。

泛型数组

不能直接创建带有泛型类型参数的数组。例如,以下代码是不合法的:

List<String>[] arrayOfLists = new List<String>[10]; // 不合法

但是,可以使用通配符 ? 创建泛型数组:

List<?>[] arrayOfLists = new List<?>[10]; // 合法

泛型和继承

泛型类不能继承自 Throwable 类,这意味着不能创建泛型异常类。

泛型和基本数据类型

泛型不能用于基本数据类型(如 intchardouble 等),只能用于引用数据类型。如果需要操作基本数据类型,可以使用对应的包装类(如 IntegerCharacterDouble 等)。

泛型的高级应用

除了基本用法和限制,泛型还具有一些高级应用,如通配符的上限和下限、泛型方法的类型推断、泛型的反射和通配符捕获等。这些高级主题超出了本篇博客的范围,但可以在进一步学习 Java 泛型时深入探讨。

泛型使用注意事项

当使用泛型时,有一些重要的注意事项和最佳实践,以确保您的代码正确、安全且易于维护。以下是一些泛型的使用注意事项:

  1. 类型擦除: 泛型信息在编译时会被擦除,这意味着在运行时无法获得泛型的实际类型参数。因此,不能在运行时检查泛型类型。例如,以下代码将引发编译错误:

    // 编译错误:无法检查泛型类型
    if (list instanceof List<String>) {
        // ...
    }
    

    要注意,虽然编译器会发出警告,但在运行时不会引发异常。

  2. 泛型数组: 直接创建带有泛型类型参数的数组是不合法的。但可以使用通配符 ? 创建泛型数组,如 List<?>[]。如果需要数组结构,通常建议使用集合(如 ListArrayList)而不是数组。

  3. 通配符捕获: 当使用通配符(例如 <?><? extends T>)时,可以捕获通配符的实际类型参数,但在方法内部无法修改通配符的类型。例如:

    public void process(List<?> list) {
        // 编译错误:无法添加元素到通配符列表
        list.add("Hello");
    }
    

    在这种情况下,可以使用带有类型参数的辅助方法来处理通配符列表。

  4. 避免原始类型: 尽量避免使用原始类型,而是使用泛型类。原始类型是泛型的历史遗留物,不安全且不推荐使用。

  5. 泛型方法类型推断: 在调用泛型方法时,可以省略类型参数,编译器会根据参数的类型自动推断出类型参数。这样可以使代码更简洁,例如:

    List<String> names = new ArrayList<>();
    names.add("Alice");
    names.add("Bob");
    
    // 类型推断:不需要指定类型参数
    String first = getFirstElement(names);
    
  6. 泛型通配符: 使用通配符可以实现灵活的泛型参数传递,但需要注意通配符的上限和下限。通配符 <? extends T> 表示类型上限,通配符 <? super T> 表示类型下限。选择合适的通配符可以提高代码的可用性和安全性。

  7. 类型转换警告: 在使用泛型时,可能会遇到类型转换警告,例如使用原始类型或未检查的转换。在遇到这些警告时,应谨慎处理,并尽量避免类型不安全的转换。

  8. 泛型和继承: 注意泛型类不能继承自 Throwable,因此不能创建泛型异常类。同时,泛型类的类型参数不会继承,例如 List<Child> 不是 List<Parent> 的子类型。

  9. 泛型和基本数据类型: 泛型不能用于基本数据类型(如 intchardouble 等),只能用于引用数据类型。如果需要操作基本数据类型,可以使用对应的包装类(如 IntegerCharacterDouble 等)。

  10. 通配符和可读性: 虽然通配符可以提高代码的灵活性,但过度使用通配符可能会降低代码的可读性。在选择是否使用通配符时,需要权衡代码的清晰度和灵活性。

总之,泛型是 Java 中强大的特性,可以提高代码的安全性和可维护性。但要谨慎使用,遵循最佳实践,以避免潜在的问题。随着更多的实践和学习,您将能够更好地利用泛型来编写高质量的 Java 代码。

结语

本篇博客介绍了 Java 泛型的基本概念、用法以及一些限制。泛型是 Java 中强大且重要的特性,它可以帮助您编写更安全、更通用的代码。通过深入学习和实践,您可以更好地理解和应用泛型,提高 Java 编程的效率和质量。希望本博客能帮助您入门和精通 Java 泛型。如果您有任何问题或需要进一步的帮助,请随时留下评论。

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

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

相关文章

nrf52832蓝牙GAP 通用访问规范

nrf52832蓝牙GAP 通用访问规范 文章目录 nrf52832蓝牙GAP 通用访问规范前言一、蓝牙GAP&#xff08;通用访问配置文件&#xff09;可以设置什么参数&#xff1f;二、使用步骤广播名称修改广播名字长度&#xff1b;全显示和自定义显示中文显示广播名称 蓝牙图标没有图标加入图标…

ArmSom-W3开发板之PCIE的开发指南(一)

1. 简介 RK3588从入门到精通本⽂介绍RK平台配置pcie的方法开发板&#xff1a;ArmSoM-W3 2、PCIE接口概述 PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;是一种用于连接计算机内部组件的高速接口标准。以下是关于PCIe接口的简要介绍&#xff1a; …

【计算机网络】 TCP流量控制——滑动窗口和累积应答

文章目录 累积应答TCP流量控制——滑动窗口 累积应答 我们前面所说的是我们每发送一个包对端就要回一个ack&#xff0c;那么这样效率太慢了&#xff0c;我们这里就有一个累积应答的机制&#xff0c;就是说我们客户端累积发送多个包&#xff0c;然后服务端再统一进行回复。 TCP…

被“多元平等共融”种草——2023谷歌开发者大会参会体验

谷歌开发者大会又称Google I/O Connect&#xff0c;是谷歌公司每年一次举办的开发者年会&#xff0c;谷歌中国的开发者大会按照惯例是在每年9月份的上海世博中心举办&#xff0c;为期两天。这两天中&#xff0c;通过主旨大会和多场连续专题演讲以及现场演示向参会人员展示谷歌产…

【Teams】Teams的组织名称变更

最近在使用Teams的过程中&#xff0c;发现有些企业创建组织的过程中创建了默认的组织&#xff1a;MSFT。如果创建组织的过程中没有修改组织名称&#xff0c;我们就会发现默认的组织名称就是MSFT。如果多个企业没有更改MSFT则可能在切换Teams账户的时候可能不知道目前Teams切换的…

Jetpack Compose基础组件之 — Text

Text的源码参数预览 Composable fun Text(text: String,modifier: Modifier Modifier,color: Color Color.Unspecified,fontSize: TextUnit TextUnit.Unspecified,fontStyle: FontStyle? null,fontWeight: FontWeight? null,fontFamily: FontFamily? null,letterSpac…

YOLO物体检测-系列教程1:YOLOV1整体解读(预选框/置信度/分类任/回归任务/损失函数/公式解析/置信度/非极大值抑制)

&#x1f388;&#x1f388;&#x1f388;YOLO 系列教程 总目录 YOLOV1整体解读 YOLOV2整体解读 YOLOV1提出论文&#xff1a;You Only Look Once: Unified, Real-Time Object Detection 1、物体检测经典方法 two-stage&#xff08;两阶段&#xff09;&#xff1a;Faster-rc…

PMP-项目启动过程组的重要性

一、什么是项目启动过程组 启动过程组包括定义一个新项目或现有项目的一个新阶段&#xff0c;授权开始该项目或阶段的一组过程。启动过程组的目的是&#xff1a;协调相关方期望与项目目的&#xff0c;告知相关方项目范围和目标&#xff0c;并商讨他们对项目及相关阶段的参与将如…

flask查询工具

fist_index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>电话查询工具</title> </head> <body><table><form action"/search_phone" method"get&…

《PostgreSQL备份与恢复:步骤与最佳实践》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

将vue项目变成可发布的npm包项目

第一步&#xff1a; 在main.ts 文件的平级上新建一个index.ts文件 &#xff0c;文件中导出你想发布的组件 第二步&#xff1a; 在package.json文件的平级上新建index.js文件 第三步&#xff1a; 修改package.json文件&#xff0c;新增命令 "buildnpm": "vu…

c#设计模式-创建型模式 之 建造者模式

简介&#xff1a; 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。意图是将一个复杂的构建与其表示相分离&#xff0c;使得同样…

LeetCode_模拟_中等_2596.检查骑士巡视方案

目录 1.题目2.思路3.代码实现&#xff08;Java&#xff09; 1.题目 骑士在一张 n x n 的棋盘上巡视。在有效的巡视方案中&#xff0c;骑士会从棋盘的左上角出发&#xff0c;并且访问棋盘上的每个格子恰好一次 。 给你一个 n x n 的整数矩阵 grid &#xff0c;由范围 [0, n * …

SAP 委外联产品 如何分摊加工费 ?

SAP 委外联产品 如何分摊加工费 &#xff1f; 目前对委外联产品分摊加工费还没好办法&#xff0c;看上去与委外副产品业务是一样的&#xff0c;除了主数据设置多了一些。 委外物料与联产品物料都设置S价&#xff0c;跑物料分类账时根据主数据设置分摊规则将差异分摊到对应的物…

获取Windows 10中的照片(旧版)下载

Windows 10中的新版照片应用&#xff0c;目前发现无法直接打开部分iOS设备上存储的照片。需要使用照片&#xff08;旧版&#xff09;才行。 但目前应用商店中无法直接搜索到照片&#xff08;旧版&#xff09;&#xff0c;因此笔者提供如下链接&#xff0c;可以直接访问并呼出W…

Swift学习内容精选(二)

Swift 类是构建代码所用的一种通用且灵活的构造体。 我们可以为类定义属性&#xff08;常量、变量&#xff09;和方法。 与其他编程语言所不同的是&#xff0c;Swift 并不要求你为自定义类去创建独立的接口和实现文件。你所要做的是在一个单一文件中定义一个类&#xff0c;系…

详解带头双向循环列表

目录 前言 一、带头双向循环链表的结构 二、 带头双向循环链表的实现 2.1链表的创建 2.2开辟新的结点 2.3初始化 2.4释放销毁 2.5链表的打印 2.7尾插 2.8尾删 2.9头插 2.10头删 三、带头双向循环链表中间随机值的插入和删除 3.1在pos位置插入x 3.2删除pos位置的…

C#回调函数学习1

回调函数&#xff08;Callback Function&#xff09;是一种函数指针&#xff0c;它指向的是由用户自己定义的回调函数。我们将这个回调函数的指针作为参数传递给另外一个函数&#xff0c;在这个函数工作完成后&#xff0c;它将通过这个回调函数的指针来回调通知调用者处理结果。…

XREAL 联合创始人吴克艰谈AR:下一代计算平台及其关键技术

// 编者按&#xff1a;一种行业观点是&#xff0c;AR或是未来十年、三十年的革命性技术&#xff0c;是下一代计算平台。近半个世纪&#xff0c;我们总能听到苹果在AR行业的创新动作&#xff0c;开辟了新的硬件范式。AR/VR行业为苹果不断欢呼的同时&#xff0c;激发了人们的好…

JAVA设计模式8:装饰模式,动态地将责任附加到对象上,扩展对象的功能

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;3年JAVA全栈开发经验&#xff0c;专注JAVA技术、系统定制、远程指导&#xff0c;致力于企业数字化转型&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;蓝桥云课讲师。 目录 一、什么是装饰模式二、…