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

Java核心技术【二十】Java泛型的基本概念和原理详解

Java泛型的基本概念和原理详解

一、泛型的基本概念

Java泛型(Generics)是Java SE 1.5(JDK 5)引入的一个新特性,它提供了一种在编译时期进行类型检查的方式,允许程序员在定义类、接口和方法时指定类型参数(Type Parameters)。这些类型参数在实例化类、实现接口或调用方法时会被具体的类型所替换,从而使得代码更加灵活、安全且易于维护。

泛型的本质是将类型参数化,即把数据类型作为一种参数传递给类或方法。这样,同一个类或方法就可以操作多种数据类型,而无需为每种数据类型编写专门的代码。

二、泛型的原理与机制

1. 泛型擦除(Type Erasure)

Java的泛型实现采用了类型擦除机制。这意味着在编译阶段,Java编译器会将泛型代码中的类型参数替换为它们的限定类型(如果没有明确限定,则默认为Object类型),并插入必要的类型转换代码。因此,在运行时,JVM中并没有泛型类型的信息,所有的泛型类型都被擦除为它们的原始类型。泛型只提供编译时类型检查,而不是运行时类型检查。

示例:

List<String> stringList = new ArrayList<>();  
stringList.add("Hello");  
  • 编译时,List<String> 被擦除为List,但编译器会确保你添加的是String类型。
  • 运行时,stringList实际上是一个原始类型的ArrayList,其中的元素被当作Object处理

2. 编译时类型检查

泛型的主要优势之一是在编译时提供类型安全检查。当使用泛型时,编译器会根据泛型参数的类型来检查代码中的类型错误。如果尝试将错误类型的对象添加到泛型集合中,或者从泛型集合中取出对象时进行了错误的类型转换,编译器会在编译时捕获这些错误,而不是等到运行时才抛出ClassCastException

示例:

List<Integer> intList = new ArrayList<>();  
intList.add("Hello"); 
  • 编译错误:不兼容的类型: String无法转换为Integer

3. 类型参数命名约定

在定义泛型类、接口或方法时,类型参数通常使用单个大写字母来命名,如T(代表Type)、E(代表Element)、K(代表Key)、V(代表Value)等。这些字母是任意的,但遵循一定的命名约定可以提高代码的可读性。

三、泛型的使用

1. 泛型类

泛型类是在类定义时声明一个或多个类型参数的类。这些类型参数在类的成员变量、方法参数、方法返回值等位置可以使用。

1)定义泛型类示例:

public class Box<T> {  private T t;public void set(T t) {this.t = t;}public T get() {return t;}
}  

2)调用泛型类示例:

public class Test {public static void main(String[] args) {// 使用示例  Box<Integer> integerBox = new Box<>();  integerBox.set(123);  //这里如果设置字符串会报错Integer value = integerBox.get();System.out.println("value:" + value);}}

2. 泛型方法

泛型方法是在方法定义时声明一个或多个类型参数的方法。这些类型参数只在该方法的作用域内有效。

1)在Box.java中添加泛型方法:

public static <T> void printArray(T[] inputArray) {  for (T element : inputArray) {  System.out.printf("%s ", element);  }  System.out.println();  
}  

2)调用示例:

// 使用示例 2 
Integer[] intArray = {1, 2, 3};  
Box.printArray(intArray);

3. 泛型接口

泛型接口与泛型类类似,也是在接口定义时声明一个或多个类型参数。实现泛型接口的类必须在实现接口时指定具体的类型参数,或者使用类型通配符来保持接口的灵活性。

示例:

public interface Pair<K, V> {public K getKey();  public V getValue();
}
public class StringIntPair implements Pair<String, Integer> {private String key;  private Integer value;  public StringIntPair(String key, Integer value) {  this.key = key;  this.value = value;  }  @Overridepublic String getKey() {return key;}@Overridepublic Integer getValue() {return value;}}

四、泛型的好处

  • 类型安全:泛型提供了编译时的类型检查,有助于减少运行时类型转换错误。
  • 消除强制类型转换:使用泛型后,大多数情况下不需要进行强制类型转换,代码更加简洁。
  • 提高代码复用性:通过泛型,可以编写更加通用的代码,适用于多种数据类型。
  • 提高代码可读性:泛型使得代码更加清晰易懂,尤其是当处理复杂的数据结构时。

综上所述,Java泛型是一种强大的特性,它通过类型擦除和编译时类型检查机制,提高了代码的安全性、复用性和可读性。掌握泛型的使用对于编写高质量的Java代码至关重要。

结束语

泛型是现代编程语言中一项极为重要的特性,它提供了编译时的类型安全检查,同时保持了代码的灵活性和复用性。理解泛型的基本概念、泛型类和泛型方法的使用,以及泛型擦除带来的类型安全问题,对于编写高质量、可维护的代码至关重要。通过合理利用泛型,开发者可以有效减少运行时错误,提升代码的整体质量。

简单动作,深刻联结。在这技术海洋,我备好舟,等你扬帆。启航吧!
🌟点击【关注】,解锁定期的技术惊喜,让灵感与知识的源泉不断涌动。
👍一个【点赞】,如同心照不宣的默契,是我们共同语言的闪亮印记。
📚【收藏】好文,搭建你的专属智慧库,让每次回望都能照亮新知之路。
源码地址:https://gitee.com/code-in-java/csdn-blog.git

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 二叉树超详细解析
  • phpstudy框架,window平台,如何开端口给局域网访问?
  • AIGC专栏12——EasyAnimateV3发布详解 支持图文生视频 最大支持960x960x144帧视频生成
  • 【QT中实现摄像头播放、以及视频录制】
  • Consul与CoreDNS的对比
  • 架构设计(2)云原生架构与实例部署
  • 【WebGIS平台】传统聚落建筑科普数字化建模平台
  • MySQL之基本查询(上)-表的增删查改
  • 如何使用 Puppeteer 避免机器人检测?
  • oracle索引字段存储数据过长,导致索引失效
  • 突破传统,实时语音技术的革命。Livekit 开源代理框架来袭
  • for循环中list触发fast-fail或不触发的原理和方法
  • windows@windows设备之间远程命令行控制方案@windows设备间使用OpenSSH
  • C语言力扣刷题12——合并区间[排序]
  • 继承关系中的访问控制
  • 【mysql】环境安装、服务启动、密码设置
  • 11111111
  • JavaScript 奇技淫巧
  • laravel 用artisan创建自己的模板
  • npx命令介绍
  • PAT A1120
  • SpiderData 2019年2月25日 DApp数据排行榜
  • SQLServer之创建显式事务
  • 原生 js 实现移动端 Touch 滑动反弹
  • ​iOS安全加固方法及实现
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • (07)Hive——窗口函数详解
  • (13):Silverlight 2 数据与通信之WebRequest
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (3)选择元素——(17)练习(Exercises)
  • (7)STL算法之交换赋值
  • (bean配置类的注解开发)学习Spring的第十三天
  • (SpringBoot)第二章:Spring创建和使用
  • (四)js前端开发中设计模式之工厂方法模式
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • .bat批处理出现中文乱码的情况
  • .Net FrameWork总结
  • .NET 使用配置文件
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .net反编译工具
  • .NET开源、简单、实用的数据库文档生成工具
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • []指针
  • [12] 使用 CUDA 加速排序算法
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体
  • [c]统计数字
  • [DNS网络] 网页无法打开、显示不全、加载卡顿缓慢 | 解决方案
  • [DP 训练] Longest Run on a Snowboard, UVa 10285