深入理解Java泛型:灵活、安全、可重用的编程利器

Java泛型是一项强大的编程特性,为程序员提供了一种灵活、类型安全、可重用的编码方式。通过泛型,我们能够编写更加通用、适应多种数据类型的代码,从而提高了代码的灵活性和可维护性。在这篇博客中,我们将深入探讨Java泛型的各个方面,并通过具体的例子来展示其用法和优势。

1. 泛型类和泛型方法

在以下代码中,printArray 方法使用了泛型类型参数 T,允许我们在运行时指定具体的类型。这种方式使得我们可以编写通用的方法来处理不同类型的数组。


public class Print {/*** 打印数组* @param inputArray* @param <T>*/public static <T> void printArray(T[] inputArray) {for (T element : inputArray) {System.out.printf("%s ", element);}System.out.println();}/*** 打印整数数组* @param inputArray*/public static void IntPrintArray(Integer[] inputArray) {for (Integer element : inputArray) {System.out.printf("%s ", element);}System.out.println();}/*** 打印字符串数组* @param inputArray*/public static void StrPrintArray(String[] inputArray) {for (String element : inputArray) {System.out.printf("%s ", element);}System.out.println();}
}

然后,我们通过一个示例程序 Method01 来展示泛型方法的应用:

/*** @ClassName: Method01* @Description: 方法1 感受泛型的好处,泛型方法* @Author: liu* @Date: 2024-03-09* @Version: 1.0**/
public class Method01 {public static void main(String[] args) {String[] stringArray = {"Hello", "World"};Integer[] integerArray = {1, 2, 3, 4, 5};System.out.println("字符串数组包含:");//StringPrint方法Print.StrPrintArray(stringArray);//编译失败 类型不一致//Print.StrPrintArray(integerArray);//泛型方法Print.printArray(stringArray);System.out.println("\n整数数组包含:");//IntegerPrint方法Print.IntPrintArray(integerArray);//编译失败 类型不一致//Print.IntPrintArray(stringArray);//泛型方法,提高代码可用性Print.printArray(integerArray);System.out.println("\n整数数组包含:");Object[] objectArray = {1, 2, 3, 4, 5, "Hello", "World"};Print.printArray(objectArray);}
}

在上述示例中,我们调用了 printArray 方法,分别传递了字符串数组和整数数组。由于泛型的存在,我们能够使用相同的方法处理不同类型的数据,提高了代码的可重用性。

再举个例子

/*** @ClassName: Method03* @Description: 方法3 可以存储任意类型的数据* @Author: liu* @Date: 2024-03-09* @Version: 1.0**/
public class Method3 {public static void main(String[] args) {// 创建一个存储整数的 Box 实例Box<Integer> integerBox = new Box<>();integerBox.setValue(42);System.out.println("Integer Value: " + integerBox.getValue());// 创建一个存储字符串的 Box 实例Box<String> stringBox = new Box<>();stringBox.setValue("Hello, Generics!");System.out.println("String Value: " + stringBox.getValue());// 创建一个存储布尔值的 Box 实例Box<Boolean> booleanBox = new Box<>();booleanBox.setValue(true);System.out.println("Boolean Value: " + booleanBox.getValue());}
}
@Data
class Box<T> {private T value;
}

2. 泛型上限和下限通配符

首先,让我们来看一个简单的泛型类和泛型方法的例子。考虑到动物(Animals)和猫(Cat)、狗(Dog)的实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Animals {public String name;public Integer age;
}@Data
public class Cat {public String name;public Integer age;public Say say;public Cat(String name, Integer age, Say say) {this.name = name;this.age = age;this.say = say;System.out.println("Cat的全参构造执行,猫边唱歌吃鱼");}public Cat() {System.out.println("Cat的无参构造执行,你创建了猫,却一笑而过!");}
}@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dog extends Animals {public String name;public Integer age;
}@Data
public class Say {public String say;public Say(String say) {this.say = say;System.out.println("说话" + say);}
}

接下来,我们将介绍泛型上限和下限通配符的概念,并通过例子 Method02 进行演示。

/*** @ClassName: Method02* @Description: 方法2, 泛型上限和下限通配符* @Author: liu* @Date: 2024-03-09* @Version: 1.0**/
public class Method02 {public static void main(String[] args) {
/*        Cat cat = new Cat();Dog dog1 = new Dog("旺财", 3);Cat cat1 = new Cat("小花", 2, new Say("喵喵喵"));Animals animal1 = new Animals("小动物", 1);List<Dog> dogList = new ArrayList<>();List<Cat> catList = new ArrayList<>();List<Animals> animalsList = new ArrayList<>();animalsList.add(animal1);dogList.add(dog1);catList.add(cat1);*/// 使用菱形操作符和双括号初始化简化代码// 在匿名内部类中,Java 并不允许使用 <> 进行菱形操作符的类型推断,还可以使用 Arrays.asList() 方法List<Dog> dogList = new ArrayList<Dog>(){private static final long serialVersionUID = -3322276720822396481L;{add(new Dog("狗王", 2));add(new Dog("狗王后", 3));}};List<Cat> catList = Arrays.asList(new Cat("猫王", 1, new Say("喵~")),new Cat());List<Animals> animalsList = new ArrayList<Animals>(){private static final long serialVersionUID = 1L;{add(new Animals("小动物", 1));}};//reason: no instance(s) of type variable(s) exist so that Cat conforms to Animals//extendMethod(catList);// 编译报错// 泛型方法调用示例extendMethod(dogList);  // 合法,List<Dog> 是 List<? extends Animals> 的子类extendMethod(animalsList);  // 合法,List<Animals> 是 List<? extends Animals> 的子类System.out.println("=====================================");superMethod(dogList);  // 合法//编译报错,List<Cat> 不是 List<? super Dog> 的子类//superMethod(catList);//编译合法,运行报错UnsupportedOperationException//superMethod(Collections.unmodifiableList(catList));superMethod(animalsList);  // 合法}public static <T extends Animals> void extendMethod(List<T> list) {// 在这里处理只包含数字类型及其子类的列表for (T element : list) {System.out.println(element);}}public static void superMethod(List<? super Dog> list) {// 在这里处理只包含数字类型及其父类的列表list.add(new Dog("二狗", 2));//list.add(new Animals("Buddy", 2)); // 编译报错for (Object element : list) {System.out.println(element);}}
}

在上述代码中,extendMethod 方法接受一个泛型列表,其中的元素必须是 Animals 类型或其子类。而 superMethod 方法则接受一个泛型列表,其中的元素必须是 Dog 类型或其父类。这样的灵活性使得我们能够对不同层次的类进行处理。

Method02 的示例程序中,我们演示了泛型上限和下限通配符的使用:

在这个示例中,我们展示了如何使用泛型上限和下限通配符来处理不同类型的列表,使得我们的代码更具通用性和灵活性。

3. 灵活处理多个泛型参数

在实际的编程场景中,有时我们需要处理多个泛型参数的情况。在这个章节,将探讨如何在Java中灵活地处理多个泛型参数,以满足更为复杂的编码需求。

代码如下:


/*** @ClassName: Method04* @Description: 演示带有多个泛型参数的Pair类的使用* @Author: 阿水* @Date: 2024-03-10* @Version: 1.0**/
public class Method04 {public static void main(String[] args) {// 创建一个带有泛型参数的Pair实例Pair<Dog, Cat> pair = new Pair<>();// 创建狗和猫的实例Dog dog = new Dog("旺财", 3);Cat cat = new Cat("小花", 2, new Say("喵喵喵"));// 设置Pair实例的值pair.setFirst(dog);pair.setSecond(cat);// 打印Pair实例的字符串表示形式以及其中的元素System.out.println(pair);System.out.println("First Element: " + pair.getFirst().getName());System.out.println("Second Element: " + pair.getSecond().getName());// 创建带有不同泛型参数的两个Pair实例Pair<String, Integer> pair1 = new Pair<>("One", 1);Pair<Double, String> pair2 = new Pair<>(6.66, "Pi");// 调用泛型方法打印Pair实例的值printPair(pair1);printPair(pair2);}/*** 打印带有泛型参数的Pair实例的值** @param pair 带有泛型参数的Pair实例* @param <T>  第一个元素的类型* @param <U>  第二个元素的类型*/public static <T, U> void printPair(Pair<T, U> pair) {System.out.println("Pair: " + pair.getFirst() + ", " + pair.getSecond());}
}/*** @ClassName: Pair* @Description: 带有两个泛型参数的Pair类* @Author: 阿水* @Date: 2024-03-10* @Version: 1.0**/
@Data
@AllArgsConstructor
@NoArgsConstructor
class Pair<T, U> {private T first;private U second;
}

运行结果如下:

4.总结

Java泛型是一项强大的编程特性,通过泛型类和泛型方法,我们能够编写通用、灵活的代码。同时,泛型上限和下限通配符使得我们能够更好地处理不同层次的类。通过这篇博客,我们深入理解了Java泛型的灵活性、安全性和可重用性,为我们的编程工作提供了更多的便利和可能性。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Flink】Flink 的八种分区策略(源码解读)

Flink 的八种分区策略&#xff08;源码解读&#xff09; 1.继承关系图1.1 接口&#xff1a;ChannelSelector1.2 抽象类&#xff1a;StreamPartitioner1.3 继承关系图 2.分区策略2.1 GlobalPartitioner2.2 ShufflePartitioner2.3 BroadcastPartitioner2.4 RebalancePartitioner2…

全栈的自我修养 ———— css中常用的布局方法flex和grid

在项目里面有两种常用的主要布局:flex和grid布局&#xff08;b站布局&#xff09;&#xff0c;今天分享给大家这两种的常用的简单方法&#xff01; 一、flex布局1、原图2、中心对齐3、主轴末尾或者开始对其4、互相间隔 二、grid布局1、基本效果2、加间隔3、放大某一个元素 一、…

政安晨:【深度学习处理实践】(四)—— 实施一个温度预测示例

在开始使用像黑盒子一样的深度学习模型解决温度预测问题之前&#xff0c;我们先尝试一种基于常识的简单方法。 它可以作为一种合理性检查&#xff0c;还可以建立一个基准&#xff0c;更高级的机器学习模型需要超越这个基准才能证明其有效性。对于一个尚没有已知解决方案的新问…

HTML 学习笔记(四)图片

<!--通过图片标签"<img src "图片路径">"来调用图片在网页中进行显示--> <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthd…

Linux网络套接字之预备知识

(&#xff61;&#xff65;∀&#xff65;)&#xff89;&#xff9e;嗨&#xff01;你好这里是ky233的主页&#xff1a;这里是ky233的主页&#xff0c;欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 目录 一、预备知识 1.理解源IP地址和目的IP地址 …

Chain of Verification(验证链、CoVe)—理解与实现

原文地址&#xff1a;Chain of Verification (CoVe) — Understanding & Implementation 2023 年 10 月 9 日 GitHub 存储库 介绍 在处理大型语言模型&#xff08;LLM&#xff09;时&#xff0c;一个重大挑战&#xff0c;特别是在事实问答中&#xff0c;是幻觉问题。当答案…

Day27:安全开发-PHP应用TP框架路由访问对象操作内置过滤绕过核心漏洞

目录 TP框架-开发-配置架构&路由&MVC模型 TP框架-安全-不安全写法&版本过滤绕过 思维导图 PHP知识点 功能&#xff1a;新闻列表&#xff0c;会员中心&#xff0c;资源下载&#xff0c;留言版&#xff0c;后台模块&#xff0c;模版引用&#xff0c;框架开发等 技…

时间感知自适应RAG(TA-ARE)

原文地址&#xff1a;Time-Aware Adaptive RAG (TA-ARE) 2024 年 3 月 1 日 介绍 随着大型语言模型&#xff08;LLM&#xff09;的出现&#xff0c;出现了新兴能力的概念。前提或假设是LLMs具有隐藏的和未知的能力&#xff0c;等待被发现。企业家们渴望在LLMs中发现一些无人知晓…

Linux学习:权限

目录 1. shell命令的工作原理与存在意义1.1 shell命令解释器存在的意义1.2 shell解释器的工作原理 2. Linux操作系统&#xff1a;用户2.1 什么是用户2.2 用户的切换操作2.3 用户权限划分的意义 3. Linux中权限的种类和意义3.1 什么是权限3.2 sudo指令与短暂提权 4. 文件类型与文…

Django模型层(附带test环境)

Django模型层(附带test环境) 目录 Django模型层(附带test环境)连接数据库Django ORM在models.py中建表允许为空指定默认值数据库迁移命令 开启测试环境建表语句补充(更改默认表名)数据的增加时间数据的时区 多表数据的增加一对多多对多 数据的删除修改数据查询数据查询所有数据…

【Claude 3】一文谈谈Anthropic(Claude) 亚马逊云科技(Bedrock)的因缘际会

文章目录 前言1. Anthropic的诞生2. Anthropic的“代表作”——Claude 3的“三驾马车”3. 亚马逊云科技介绍4. 强大的全托管服务平台——Amazon Bedrock5. 亚马逊云科技(AWS)和Anthropic的联系6. Claude 3模型与Bedrock托管平台的关系7. Clude 3限时体验入口分享【⚠️截止3月1…

力扣---腐烂的橘子

题目&#xff1a; bfs思路&#xff1a; 感觉bfs还是很容易想到的&#xff0c;首先定义一个双端队列&#xff08;队列也是可以的~&#xff09;&#xff0c;如果值为2&#xff0c;则入队列&#xff0c;我这里将队列中的元素定义为pair<int,int>。第一个int记录在数组中的位…