Java 泛型与集合的深入解析:原理、应用与实践
泛型的基本原理
为什么需要泛型
在Java 5之前,Java的集合类只能存储Object
类型的对象。这意味着,存储在集合中的对象在取出时需要进行类型转换,这不仅繁琐,而且容易出错。泛型通过在编译时进行类型检查,确保类型安全,减少了运行时错误。
泛型的定义
泛型通过类型参数来实现,这些类型参数在使用时被具体的类型替换。常见的类型参数命名如下:
T
:Type(类型)E
:Element(元素)K
:Key(键)V
:Value(值)
泛型类
泛型类是在类定义中使用类型参数。例如:
class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}
}
在使用泛型类时,需要指定具体的类型:
public class GenericClassExample {public static void main(String[] args) {Box<String> stringBox = new Box<>();stringBox.setContent("Hello, World!");System.out.println(stringBox.getContent()); // 输出: Hello, World!Box<Integer> integerBox = new Box<>();integerBox.setContent(123);System.out.println(integerBox.getContent()); // 输出: 123}
}
泛型方法
泛型方法是在方法定义中使用类型参数。类型参数在方法名之前用尖括号<>
指定。例如:
public class GenericMethodExample {public static <T> void printArray(T[] array) {for (T element : array) {System.out.print(element + " ");}System.out.println();}public static void main(String[] args) {Integer[] intArray = {1, 2, 3, 4, 5};String[] stringArray = {"A", "B", "C", "D", "E"};printArray(intArray); // 输出: 1 2 3 4 5 printArray(stringArray); // 输出: A B C D E }
}
泛型和集合
Java集合框架是处理一组对象的标准方法。常见的集合包括List
、Set
和Map
。结合泛型使用集合,可以提高类型安全性和代码的可读性。
使用泛型集合
import java.util.ArrayList;
import java.util.List;public class GenericCollectionExample {public static void main(String[] args) {// 创建一个用于存储字符串的泛型列表List<String> stringList = new ArrayList<>();// 向列表中添加字符串stringList.add("Hello");stringList.add("World");// 使用增强型 for 循环遍历并打印列表中的每个字符串for (String str : stringList) {System.out.println(str);}}
}
//程序运行后,输出结果为:
//Hello
//World
在这个例子中,List<String>
确保了stringList
只能包含String
类型的元素。
通配符
通配符用于在泛型中表示未知类型,有三种主要形式:
- 无界通配符:
<?>
,表示任何类型。 - 有界通配符(上界):
<? extends T>
,表示类型T及其子类型。 - 有界通配符(下界):
<? super T>
,表示类型T及其父类型。
无界通配符
无界通配符<?>
表示任何类型。例如:
import java.util.ArrayList;
import java.util.List;public class WildcardExample {public static void printList(List<?> list) {for (Object elem : list) {System.out.print(elem + " ");}System.out.println();}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();intList.add(1);intList.add(2);intList.add(3);List<String> stringList = new ArrayList<>();stringList.add("A");stringList.add("B");stringList.add("C");printList(intList); // 输出: 1 2 3 printList(stringList); // 输出: A B C }
}
有界通配符(上界)
有界通配符<? extends T>
表示类型T及其子类型。例如:
import java.util.ArrayList;
import java.util.List;public class BoundedWildcardExample {public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number number : list) {sum += number.doubleValue();}return sum;}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();intList.add(1);intList.add(2);intList.add(3);List<Double> doubleList = new ArrayList<>();doubleList.add(1.1);doubleList.add(2.2);doubleList.add(3.3);System.out.println("Sum of intList: " + sumOfList(intList)); // 输出: Sum of intList: 6.0System.out.println("Sum of doubleList: " + sumOfList(doubleList)); // 输出: Sum of doubleList: 6.6}
}
有界通配符(下界)
有界通配符<? super T>
表示类型T及其父类型。例如:
import java.util.ArrayList;
import java.util.List;public class LowerBoundedWildcardExample {public static void addNumbers(List<? super Integer> list) {list.add(1);list.add(2);list.add(3);}public static void main(String[] args) {List<Number> numberList = new ArrayList<>();addNumbers(numberList);for (Number number : numberList) {System.out.println(number);}}
}
泛型和继承
泛型不支持多态,例如,List<Number>
不能被赋值为List<Integer>
。但是可以通过使用通配符来实现类似的效果。
示例:泛型和继承
import java.util.ArrayList;
import java.util.List;class Person {private String name;public Person(String name) {this.name = name;}public String getName() {return name;}
}class Employee extends Person {public Employee(String name) {super(name);}
}public class GenericInheritanceExample {public static void printNames(List<? extends Person> people) {for (Person person : people) {System.out.println(person.getName());}}public static void main(String[] args) {List<Employee> employees = new ArrayList<>();employees.add(new Employee("Alice"));employees.add(new Employee("Bob"));printNames(employees); // 输出: Alice Bob}
}
总结
通过以上更详细的解释和示例,我们可以更深入地理解泛型和集合的使用:
- 泛型类:定义包含类型参数的类,使用时指定具体类型。
- 泛型方法:定义包含类型参数的方法,使用时指定具体类型。
- 集合和泛型:使用泛型集合可以保证类型安全。
- 通配符:表示未知类型,提供更灵活的类型控制。
- 泛型和继承:使用通配符实现泛型的多态性。
相关文章:
Java 泛型与集合的深入解析:原理、应用与实践
泛型的基本原理 为什么需要泛型 在Java 5之前,Java的集合类只能存储Object类型的对象。这意味着,存储在集合中的对象在取出时需要进行类型转换,这不仅繁琐,而且容易出错。泛型通过在编译时进行类型检查,确保类型安全…...
Oracle 数据库的自动化工具:AWR 和 ASM
Oracle 数据库提供了一系列工具和技术,以提高数据库管理的效率和性能。其中,AWR和 ASM是两个关键组件。本文将详细介绍 AWR 和 ASM 的功能及其在数据库管理中的重要性。 AWR AWR 是 Oracle 数据库的一个核心部分,用于收集、处理和维护数据库…...
java技术专家面试指南50问【java学习+面试宝典】(五)
Dubbo需要 Web 容器吗? 不需要,如果硬要用 Web 容器,只会增加复杂性,也浪费资源。 一个字符串类型的值能存储最大容量是多少? 512M 什么是Kubectl? Kubectl是一个平台,您可以使用该平台将命…...

Elasticsearch之深入聚合查询
1、正排索引 1.1 正排索引(doc values )和倒排索引 概念:从广义来说,doc values 本质上是一个序列化的 列式存储 。列式存储 适用于聚合、排序、脚本等操作,所有的数字、地理坐标、日期、IP 和不分词( no…...

大模型:分本分割模型
目录 一、文本分割 二、BERT文本分割模型 三、部署模型 3.1 下载模型 3.2 安装依赖 3.3 部署模型 3.4 运行服务 四、测试模型 一、文本分割 文本分割是自然语言处理中的一项基础任务,目标是将连续的文本切分成有意义的片段,这些片段可以是句子、…...

数据预处理 #数据挖掘 #python
数据分析中的预处理步骤是数据分析流程中的重要环节,它的目的是清洗、转换和整理原始数据,以便后续的分析能够准确、有效。预处理通常包括以下几个关键步骤: 数据收集:确定数据来源,可能是数据库、文件、API或网络抓取…...

VS2022 使用C++访问 mariadb 数据库
首先,下载 MariaDB Connector/C++ 库 MariaDB Products & Tools Downloads | MariaDB 第二步,安装后 第三步,写代码 #include <iostream> #include <cstring> #include <memory> #include <windows.h>#include <mariadb/conncpp.hpp>…...
kotlin 语法糖
Use of “when” Expression Instead of “switch” fun getDayOfWeek(day: Int): String {return when (day) {1 -> "Monday"2 -> "Tuesday"3 -> "Wednesday"4 -> "Thursday"5 -> "Friday"6 -> "Sa…...

.NET MAUI Sqlite数据库操作(一)
一、安装 NuGet 包 安装 sqlite-net-pcl 安装 SQLitePCLRawEx.bundle_green 二、配置数据库(数据库文件名和路径) namespace TodoSQLite; public static class Constants {public const string DatabaseFilename "TodoSQLite.db3";//数据库…...

SQL 窗口函数
1.窗口函数之排序函数 RANK, DENSE_RANK, ROW_NUMBER RANK函数 计算排序时,如果存在相同位次的记录,则会跳过之后的位次 有 3 条记录排在第 1 位时: 1 位、1 位、1 位、4 位…DENSE_RANK函数 同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次 有 3 条记录排在…...

staruml怎么合并多个Project工程文件
如图现在有两个staruml文件 现在我想要把project2合并到project1里面 步骤如下: 1、首先打开project2 2、如图选择导出Fragment 3、选中自己想导出的模块(可以不止一个) 4、将其保存在桌面 5、打开project1 6、选择导入 7、选中刚刚…...

设计模式——外观模式
外观模式(Facade) 为系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 #include <iostream>using namespace std;// 四个系统子类 class SubSystemOne { public:void MethodOne(){cout <&l…...

开源-Docker部署Cook菜谱工具
开源-Docker部署Cook菜谱工具 文章目录 开源-Docker部署Cook菜谱工具介绍资源列表基础环境一、安装Docker二、配置加速器三、查看Docker版本四、拉取cook镜像五、部署cook菜谱工具5.1、创建cook容器5.2、查看容器运行状态5.3、查看cook容器日志 六、访问cook菜谱服务6.1、访问c…...

使用PHP对接企业微信审批接口的问题与解决办法(二)
在现代企业中,审批流程是非常重要的一环,它涉及到企业内部各种业务流程的规范和高效运转。而随着企业微信的流行,许多企业希望将审批流程整合到企业微信中,以实现更便捷的审批操作。本文将介绍如何使用PHP对接企业微信审批接口&am…...

RK3288 android7.1 实现ota升级时清除用户数据
一,OTA简介(整包,差分包) OTA全称为Over-The-Air technology(空中下载技术),通过移动通信的接口实现对软件进行远程管理。 1. 用途: OTA两种类型最大的区别莫过于他们的”出发点“(我们对两种不同升级包的创建&…...
okHttp的https请求忽略ssl证书认证
使用okhttp请求第三方https接口返回异常 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target意思就是非安全的调用&#…...
在Java中使用Spring Boot设置全局的BusinessException
在线工具站 推荐一个程序员在线工具站:程序员常用工具(http://cxytools.com),有时间戳、JSON格式化、文本对比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。 程序员资料站 推荐一个程序员编程资料站:…...
Java 异常处理 -- Java 语言的异常、异常链与断言
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 009 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自…...
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台 Spring Cloud Nacos 是 Spring Cloud 生态系统中的一个子项目,提供了服务注册与发现、配置管理等功能,基于 Alibaba 开源的 Nacos 项目。Nacos 是一个易于使用的动态服务发现、配置管…...

java多线程临界区介绍
在Java多线程编程中,"临界区"是指一段必须互斥执行的代码区域。当多个线程访问共享资源时,为了防止数据不一致或逻辑错误,需要确保同一时刻只有一个线程可以进入临界区。Java提供了多种机制来实现这一点,例如synchroniz…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...

ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...