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

news2024/10/2 8:25:51

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.coloradmin.cn/o/1505375.html

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

相关文章

selenium元素定位问题

具体网页信息如下&#xff1a; 定位的时候driver.find_element(By.CLASS_NAME, 方法搞不定。 定位方法&#xff1a; 方法一&#xff1a;通过文本定位 driver.find_element(By.XPATH, "//*[text()高分一号]").click() time.sleep(3) 如果是部分文字 #部分文字py…

GFP-GAN环境搭建推理测试

引子 近期&#xff0c;文生图&#xff0c;wav2lip很火&#xff0c;文生图&#xff0c;见识的太多&#xff0c;不多说了。wav2lip其通过语音驱动唇部动作并对视频质量进行修复&#xff0c;里面一般涉及到三个步骤&#xff0c;文本到语音转化&#xff0c;语音驱动唇部动作&#…

HIVE伪分布安装

引言 Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,类似于RDBMS(关系型数据库,如MySQL、Oracle、PgSQL),并提供类SQL的查询功能。 实验准备 1.搭建好伪分布安装模式的Hadoop的虚拟机,并配置了Linux网络。(可看我前面发布的文章) 2.apache…

美国签证|附面签相关事项√

小伙伴最近都忙着办签证吧&#xff01;但是需要注意的是&#xff0c;美国的签证跟其他任何国家的签证不同&#xff0c;并不是办理了就一定拿得到&#xff0c;据说概率是50%左右。所以办理美国签证&#xff0c;不要太着急啦&#xff01;先来了解一下美国签证的相片该怎么拍叭 ✅…

NPP VIIRS卫星数据介绍及获取

VIIRS&#xff08;Visible infrared Imaging Radiometer&#xff09;可见光红外成像辐射仪。扫描式成像辐射仪&#xff0c;可收集陆地、大气、冰层和海洋在可见光和红外波段的辐射图像。它是高分辨率辐射仪AVHRR和地球观测系列中分辨率成像光谱仪MODIS系列的拓展和改进。VIIRS数…

雷卯推荐电磁兼容保护器件-PPTC自恢复保险丝

一、PPTC的简介 自恢复保险丝, 简称PPTC。是一种正温度系数聚合物热敏电阻&#xff0c;作过流保护用&#xff0c;可代替电流保险丝。 电路正常工作时它的阻值很小&#xff08;压降很小&#xff09;&#xff0c;当电路出现过流使它温度升高时&#xff0c;阻值急剧增大几个数量级…

运行时错误‘53’:文件未找到:MathPage.WLL。Word粘贴复制时报错解决方案!

最近写文章使用 Word 时&#xff0c;粘贴复制总是出现这个报错&#xff0c;不能 ctrlc 和 v 好叫人苦恼。百度大致检索了一些过程&#xff0c;仍然有必要记录自己的问题解决过程。 快让本文进你的文件夹吃灰吧~ 报错如下&#xff1a; 运行时错误‘53’&#xff1a; 文件未找…

C++特殊类设计【特殊类 || 单例对象 || 饿汉模式 || 懒汉模式】

目录 1. 只在堆上创建的类 2. 只允许在栈上创建的类 3. 不能被继承的类 4. 不能被拷贝的类 5. 设计一个类&#xff0c;只能创建一个对象&#xff08;单例对象&#xff09; 饿汉模式 懒汉模式 嗨&#xff01;收到一张超美的风景图&#xff0c;愿你每天都能顺心&#xff0…

Java中常用的集合及方法(2)

在Java&#xff08;JDK8&#xff09;中&#xff0c;集合&#xff08;Collection&#xff09;是数据结构的实现&#xff0c;用于存储和操作对象集合。 集合&#xff08;Collection&#xff09;中包含的一般类或接口&#xff1a; 在这其中呢&#xff0c;我们经常使用的其实就是L…

实验一:华为VRP系统的基本操作

1.1实验介绍 1.1.1关于本实验 本实验通过配置华为设备&#xff0c;了解并熟悉华为VRP系统的基本操作 1.1.2实验目的 理解命令行视图的含义以及进入离开命令行视图的方法 掌握一些常见的命令 掌握命令行在线帮助的方法 掌握如何撤销命令 掌握如何使用命令快捷键 1.1.3实验组网 …

数据结构(十)——头插法和尾插法建立单链表

&#x1f600;前言 在数据结构中&#xff0c;单链表是一种常见的数据结构&#xff0c;它由一个头节点和若干个数据节点组成。创建单链表的过程可以通过头插法或尾插法来实现。头插法是将新节点插入到链表的头部&#xff0c;而尾插法是将新节点插入到链表的尾部。本文将介绍头插…

qt 格式化打印 日志 QMessagePattern 格式词法语法及设置

一、qt源码格式化日志 关键内部类 QMessagePattern qt为 格式化打印日志 提供了一个简易的 pattern(模式/格式) 词法解析的简易的内部类QMessagePattern,作用是获取和解析自定义的日志格式信息。 该类在qt的专门精心日志操作的源码文件Src\qtbase\src\corelib\global\qloggi…

ChatGPT预训练的奥秘:大规模数据、Transformer架构与自回归学习【文末送书-31】

文章目录 ChatGPT原理与架构ChatGPT的预训练ChatGPT的迁移学习ChatGPT的中间件编程 ChatGPT原理与架构&#xff1a;大模型的预训练、迁移和中间件编程【文末送书-31】 ChatGPT原理与架构 近年来&#xff0c;人工智能领域取得了巨大的进展&#xff0c;其中自然语言处理&#xf…

微信小程序onLoad加载定义好的函数

这里小程序开发中容易犯的错误-1 给客户做一个程序。需要在页面加载的时候在onLoad(options){}中加载定义好的函数&#xff0c;代码如下 onLoad(options) {get_week_()},运行时老报错 后来修改为正确的代码 onLoad(options) {this.get_week_()//必须加this},再尝试运行&#x…

java学习(Arrays类和System类)

目录 一.Arrays类 二.System常见方法 一.Arrays类 Arrays包含了一系 列静态方法&#xff0c;用于管理或操作数组&#xff08;比如排序和搜索&#xff09; Integer[] s{1,2,3};//1.Arrays.toString方法&#xff0c;遍历数组//2.Arrays.sortArrays.sort(s);//默认排序&#xf…

幕译--本地字幕生成与翻译--Whisper客户端

幕译–本地字幕生成与翻译 本地离线的字幕生成与翻译&#xff0c;支持GPU加速。可免费试用&#xff0c;无次数限制 基于Whisper&#xff0c;希望做最好的Whisper客户端 功能介绍 本地离线&#xff0c;不用担心隐私问题支持GPU加速支持多种模型支持&#xff08;中文、英语、日…

Anaconda prompt运行打开jupyter notebook 指令出错解决方案

一、打不开jupyter notebook网页 报错如下&#xff1a; Traceback (most recent call last): File “D:\anaconda3\lib\site-packages\notebook\traittypes.py”, line 235, in _resolve_classes klass self._resolve_string(klass) File “C:\Users\DELL\AppData\Roaming\Py…

idea2023版使用废弃类没有删除线处理方法

idea2023版使用废弃类没有删除线处理方法 新版Idea使用废弃类时,默认是黄色警告处理方法1. 打开file -> setting2. 编辑(Editor) -> 检查(Inspections) -> 搜索Deprecated API usage 新版Idea使用废弃类时,默认是黄色警告 处理方法 1. 打开file -> setting 2. 编…

Linux系统架构----LNMP平台部署中部署wordpress

Linux系统架构----LNMP平台部署中部署wordpress 一、LNMP的概述 LNMP为Linux平台&#xff0c;Nginx web服务软件&#xff0c;mysql数据库软件&#xff0c;PHP编辑语言LNMP系统架构相对于LAMP的优点是LNMP比较节省内存&#xff0c;主要支持静态请求&#xff0c;但在访问量大的…

Excel中的subtotal函数

咋一看subtotal函数&#xff0c;感觉很陌生&#xff0c;但其实这个函数我们有可能在无意中碰到过。如果经常有求和需求的小伙伴&#xff0c;碰到这个函数概率比较大&#xff0c;只要在筛选的情况下&#xff0c;进行自动求和&#xff0c;都会出现这个公式。那这个函数是怎么用的…