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

Java中的泛型类型参数详解

Java中的泛型机制为开发者提供了一种编写通用代码的强大工具,使得代码在编译时可以进行类型检查,从而减少运行时的错误。泛型类型参数可以帮助我们编写更加灵活和类型安全的代码。在Java的泛型类型参数中,我们经常会看到一些常见的符号,如?TKVE等。本文将详细解释这些符号的含义及其使用场景,并结合示例代码进行说明。

1. ?(通配符)

1.1 定义位置

?是一种通配符类型参数,通常用于方法签名中作为类型参数的占位符。

1.2 使用场景

?主要用于限定集合的读取操作,例如读取列表元素,但是不能写入。它可以出现在方法参数或局部变量的声明中。

1.3 具体性

?是一个不确定的类型,表示“任意类型”。这意味着你可以将任何类型的对象放入这个引用中,但只能进行受限的操作,因为编译器无法知道确切的类型。

示例:

import java.util.ArrayList;
import java.util.List;public class WildcardExample {public static void printList(List<?> list) {for (Object obj : list) {System.out.println(obj);}}public static void main(String[] args) {List<String> stringList = new ArrayList<>();stringList.add("Apple");stringList.add("Banana");printList(stringList);}
}

在上面的示例中,printList方法接受一个通配符类型的列表,并可以打印列表中的元素。

2. T(类型)

2.1 定义位置

T(或其他字符)是在类或方法上声明的类型参数,它代表一个未知的具体类型。

2.2 使用场景

T通常用作类或接口中的类型参数,在整个类或接口的上下文中可以多次使用。例如,你可能有一个List类型的成员变量,并且有多个返回值为T的方法。

2.3 具体性

T可以指定为任何非基本类型,包括具体的类、接口或者其他的类型参数。当你需要在一个范围内操作同一种未知类型时,会使用到T

示例:

public class Box<T> {private T t;public void set(T t) {this.t = t;}public T get() {return t;}public static void main(String[] args) {Box<Integer> integerBox = new Box<>();integerBox.set(10);System.out.println("Box contains: " + integerBox.get());}
}

在上面的示例中,Box类使用了类型参数T来定义一个泛型类,可以存储任意类型的数据,并且在main方法中实例化了一个Box<Integer>对象来存储整数。

3. KV(键和值)

3.1 定义位置

KV通常用在表示键值对的泛型类或接口中。

3.2 使用场景

KV通常用于表示键值对中的键和值的类型。在Map接口中,K表示键的类型,V表示值的类型。

示例:

import java.util.HashMap;
import java.util.Map;public class KeyValueExample {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("One", 1);map.put("Two", 2);System.out.println("Value for key 'One': " + map.get("One"));}
}

在上面的示例中,使用了Map接口来存储键值对,其中K表示键的类型为StringV表示值的类型为Integer

4. E(元素)

4.1 定义位置

E通常用来表示集合中的元素类型。

4.2 使用场景

E通常用于表示集合中的元素类型。在List接口中,E表示列表中元素的类型。

示例:

import java.util.ArrayList;
import java.util.List;public class ElementExample {public static void main(String[] args) {List<String> stringList = new ArrayList<>();stringList.add("Hello");stringList.add("World");System.out.println("Element at index 0: " + stringList.get(0));}
}

在上面的示例中,创建了一个List<String>类型的列表,并向其中添加了两个字符串元素。然后通过get方法获取索引为0的元素。

5. 示例总结

为了更好地理解这些类型参数的用法,下面是一个综合示例:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;public class GenericExample {// 使用Tpublic static class Box<T> {private T t;public void set(T t) {this.t = t;}public T get() {return t;}}// 使用K和Vpublic static class Dictionary<K, V> {private Map<K, V> map = new HashMap<>();public void add(K key, V value) {map.put(key, value);}public V get(K key) {return map.get(key);}}// 使用Epublic static class CustomList<E> {private List<E> list = new ArrayList<>();public void add(E element) {list.add(element);}public E get(int index) {return list.get(index);}}// 使用通配符public static void printList(List<?> list) {for (Object obj : list) {System.out.println(obj);}}public static void main(String[] args) {// 使用BoxBox<Integer> integerBox = new Box<>();integerBox.set(10);System.out.println("Box contains: " + integerBox.get());// 使用DictionaryDictionary<String, Integer> dictionary = new Dictionary<>();dictionary.add("One", 1);dictionary.add("Two", 2);System.out.println("Dictionary key 'One': " + dictionary.get("One"));// 使用CustomListCustomList<String> customList = new CustomList<>();customList.add("Hello");customList.add("World");System.out.println("CustomList element at index 0: " + customList.get(0));// 使用通配符List<String> stringList = new ArrayList<>();stringList.add("Apple");stringList.add("Banana");printList(stringList);}
}

6. 结论

理解Java中的泛型类型参数对于编写类型安全、灵活的代码至关重要。通过熟悉?TKVE的含义及其使用场景,开发者可以更好地利用Java泛型机制,编写出更为通用和高效的代码。希望本文对你理解和使用Java泛型有所帮助。

相关文章:

  • 代碼隨想录 day22|day23
  • 7EPhone云手机各功能详解
  • Java 面试题:Java 的动态代理是基于什么原理?
  • js文件 .mjs和.umd.js结尾的文件的区别
  • 【光伏预测】基于BP神经网络实现光伏发电功率预测附Matlab代码
  • Spring Cloud Gateway 集成 Nacos、Knife4j
  • 计算机网络7——网络安全3 互联网使用的安全协议
  • 网关(Gateway)- 自定义过滤器工厂
  • 基于安卓的虫害识别软件设计--(2)模型性能可视化|混淆矩阵、热力图
  • 【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版6(附带项目源码)
  • x264 参考帧管理原理:b_ref_reorder 数组变量
  • Vue:路由管理vue-router
  • 信息标记形式 (XML, JSON, YAML)
  • DeepFace ——用于高级人脸识别算法探索与应用
  • 【Python】Python异步编程
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • docker-consul
  • JS实现简单的MVC模式开发小游戏
  • Mysql5.6主从复制
  • node和express搭建代理服务器(源码)
  • Objective-C 中关联引用的概念
  • REST架构的思考
  • 前端技术周刊 2019-01-14:客户端存储
  • 通过几道题目学习二叉搜索树
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 昨天1024程序员节,我故意写了个死循环~
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • (003)SlickEdit Unity的补全
  • (52)只出现一次的数字III
  • (poj1.2.1)1970(筛选法模拟)
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (二)Linux——Linux常用指令
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)winform之ListView
  • (转)机器学习的数学基础(1)--Dirichlet分布
  • *算法训练(leetcode)第四十天 | 647. 回文子串、516. 最长回文子序列
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .Net7 环境安装配置
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .sys文件乱码_python vscode输出乱码
  • @Autowired 与@Resource的区别
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • @ModelAttribute使用详解
  • @RequestParam详解
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [2010-8-30]