Java之泛型:解读类型安全的利器

哈喽,各位小伙伴们,你们好呀,我是喵手。

今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在Java开发中,经常需要处理各种数据类型。但是,传统的Java使用Object类型作为通用数据类型会存在一些问题,如数据类型的转换等。Java泛型的出现就是为了解决这些问题。

摘要

本文将介绍Java泛型的基本概念、语法和应用场景。通过对源代码的分析和案例的讲解,掌握泛型的使用方法和操作技巧,同时分析泛型的优缺点,并介绍相应的应用实例。最后,通过测试用例对泛型的使用进行验证,总结泛型的特点和使用场景。

泛型

简介

Java泛型是Java 5的新特性,是一种将数据类型参数化的机制。它可以使编译器在编译时强制进行类型检查,从而提高代码的可读性和安全性。

泛型可以在类、接口、方法中定义类型参数,使得它们可以使用不同类型的对象而不需要进行数据类型转换。泛型的出现使得程序员可以编写更加通用、类型安全、可重用和简洁的代码。

源代码解析

Java泛型的关键就在于定义类型参数。Java泛型的定义采用尖括号"<>"将类型参数括在一起,如下所示:

java 复制代码
class ClassName<T> {  
    // ...
}

其中,T为类型参数,可以是任意非关键字的标识符。通过使用T来代表类型参数,可以在类或方法内部使用该类型。通过在实例化类或调用方法时指定具体类型,可以在编译时进行类型检查。

这是一个泛型类定义,其中 T 是泛型类型参数。它表示该类可以接受任意类型的参数。在类的定义中,可以使用 T 作为类型参数定义类中的各种成员变量、方法或构造函数等。在实例化该泛型类时,会指定实际的类型参数来替换 T。例如:

ini 复制代码
ClassName<String> instance = new ClassName<>();

这里实例化了一个 ClassName 类,其中 T 被替换为 String 类型。这意味着在该实例中,可以使用 String 类型的成员变量、方法或构造函数等。

除了类型参数,还有通配符类型参数?,可以用来表示不确定的类型。例如:

java 复制代码
public void printList(List<?> list) {
  // ...
}

该方法接受一个List类型的参数,该List中的元素类型可以是任意类型,但是不确定具体是什么类型。

应用场景案例

集合类中使用泛型

在Java集合类中,最常见的使用泛型的地方是在List、Set和Map等容器类中。例如:

java 复制代码
List<String> list = new ArrayList<String>();
Set<Integer> set = new HashSet<Integer>();
Map<String, Integer> map = new HashMap<String, Integer>();

这里定义了一个List类型的集合,其中只能添加String类型的元素;定义了一个Set类型的集合,其中只能添加Integer类型的元素;定义了一个Map类型的集合,其中Key的类型是String,Value的类型是Integer。

自定义泛型类和泛型方法

我们也可以自定义泛型类和泛型方法。例如,我们定义一个泛型类来表示一对数据:

java 复制代码
class Pair<T, V> {
  private T first;
  private V second;
  public Pair(T first, V second) {
    this.first = first;
    this.second = second;
  }
  // 省略其他代码
}

这里定义了一个类Pair,它包含两个类型参数TV,分别表示第一个数据和第二个数据的类型。我们还可以定义泛型方法来操作泛型类型:

java 复制代码
public static <T> T getMax(T[] array) {
  T max = array[0];
  for (int i = 1; i < array.length; i++) {
    if (array[i].compareTo(max) > 0) {
      max = array[i];
    }
  }
  return max;
}

该方法接收一个泛型数组,返回其中最大的元素。这里使用了类型参数T表示数组中元素的类型。通过compareTo方法比较数组中元素的大小,返回最大元素。

优缺点分析

优点

  1. 提高代码的可读性和安全性;
  2. 实现了代码的类型安全检查,减少了运行时的错误;
  3. 可以在编译时检查代码的类型安全,避免了数据类型转换的问题;
  4. 实现了代码的重用性和通用性。

缺点

  1. 在某些情况下,使用泛型会导致代码的可读性降低;
  2. 泛型的类型参数不能是基本数据类型,只能使用其对应的包装类;
  3. 不能使用泛型数组,只能使用泛型容器。

类代码方法介绍

泛型类

在Java中,泛型类用<T>来替代具体的数据类型。

java 复制代码
package com.example.javase.se.classes.generic;

import java.util.List;

/**
 * @Author ms
 * @Date 2023-11-05 19:10
 */
class Pair<T extends Comparable<T>, V> {

    private T first;
    private V second;

    public Pair(T first, V second) {
        this.first = first;
        this.second = second;
    }

    public Pair() {
    }


    public static Integer getMax(List<Pair<String, Integer>> array) {
        Integer max = array.get(0).second;
        for (int i = 1; i < array.size(); i++) {
            if (array.get(i).second > max) {
                max = array.get(i).second;
            }
        }
        return max;
    }

    @Override
    public String toString() {
        return "Pair{" +
                "first=" + first +
                ", second=" + second +
                '}';
    }
}

这里定义了一个泛型类Pair,包含两个类型参数TV,分别表示第一个数据和第二个数据的类型。通过<T, V>声明类型参数。

该代码定义了一个泛型类Pair,其中含有两个成员变量firstsecond,分别表示泛型类型TV的第一个和第二个值。类中包含了一个有限制的泛型方法getMax,用于返回一个列表中第二个值最大的整数。该方法使用了通配符? extends Comparable<?>来限制泛型类型T必须实现Comparable接口,以便能够进行比较操作。在实例化该类时,可以指定TV的具体类型,也可以不指定,使用默认值。类中还包含了一个重写的toString方法,用于将实例对象转化为字符串。

泛型方法

在Java中,泛型方法需要在方法名前面添加类型参数列表,用<T>来替代具体的数据类型。

java 复制代码
    public static Integer getMax(List<Pair<String, Integer>> array) {
        Integer max = array.get(0).second;
        for (int i = 1; i < array.size(); i++) {
            if (array.get(i).second > max) {
                max = array.get(i).second;
            }
        }
        return max;
    }

这里定义了一个泛型方法getMax,它接收一个泛型数组,并返回其中最大的元素。通过<T>声明类型参数。

通配符

通配符可以用来表示不确定的类型,写法为<?>。例如:

java 复制代码
public void printList(List<?> list) {
  // ...
}

这里定义了一个方法printList,它接收一个List类型的参数,该List中的元素类型可以是任何类型。

测试用例

java 复制代码
package com.example.javase.se.classes.generic;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author ms
 * @Date 2023-11-05 19:10
 */
public class Test {
    public static void main(String[] args) {
        Pair<String, Integer> p1 = new Pair<>("Java", 5);
        Pair<String, Integer> p2 = new Pair<>("Python", 7);
        Pair<String, Integer> p3 = new Pair<>("C++", 3);

        List<Pair<String, Integer>> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        Integer maxPair = Pair.getMax(list);
        System.out.println("Max Pair: " + maxPair);
    }
}

该测试用例测试了Pair类和Pair类的泛型方法getMax。首先创建了三个Pair对象,并将它们添加到一个List中。然后调用getMax方法,返回其中最大的元素。

测试结果

根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

测试代码分析

根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

这段代码演示了如何使用泛型类Pair及其静态方法getMax来实现获取列表中最大值的功能。

首先,我们定义了三个Pair对象p1、p2、p3,这些对象分别包含了一个String类型的值和一个Integer类型的值。

接着,我们创建了一个List对象list,并向其添加了p1、p2、p3三个对象。

最后,我们调用Pair类的静态方法getMax来获取list列表中所有Pair对象中的最大值,并将结果保存在一个Integer类型的变量maxPair中。最终,我们将maxPair打印输出。

值得注意的是,因为Pair类中定义了泛型类型<T extends Comparable>,所以我们才可以使用Pair类提供的getMax方法来获取最大值。此外,我们定义的列表list中的元素类型也必须与Pair对象的类型一致,即都是Pair<String, Integer>类型。

小结

本文介绍了Java泛型的基本概念、语法和应用场景。通过对源代码的分析和案例的讲解,掌握了泛型的使用方法和操作技巧,同时分析了泛型的优缺点,并介绍了相应的应用实例。最后,通过测试用例对泛型的使用进行了验证,总结了泛型的特点和使用场景。

总结

Java泛型是Java 5的新特性,是一种将数据类型参数化的机制。它可以使编译器在编译时强制进行类型检查,从而提高代码的可读性和安全性。泛型可以在类、接口、方法中定义类型参数,使得它们可以使用不同类型的对象而不需要进行数据类型转换。泛型的出现使得程序员可以编写更加通用、类型安全、可重用和简洁的代码。

... ...

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

... ...

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

相关推荐
测试开发Kevin2 小时前
小tip:换行符CRLF 和 LF 的区别以及二者在实际项目中的影响
java·开发语言·python
笨手笨脚の2 小时前
Redis: Thread limit exceeded replacing blocked worker
java·redis·forkjoin·thread limit
Lenyiin2 小时前
Linux 基础IO
java·linux·服务器
松☆2 小时前
Dart 核心语法精讲:从空安全到流程控制(3)
android·java·开发语言
编码者卢布3 小时前
【Azure Storage Account】Azure Table Storage 跨区批量迁移方案
后端·python·flask
编码者卢布3 小时前
【App Service】Java应用上传文件功能部署在App Service Windows上报错 413 Payload Too Large
java·开发语言·windows
q行3 小时前
Spring概述(含单例设计模式和工厂设计模式)
java·spring
好好研究4 小时前
SpringBoot扩展SpringMVC
java·spring boot·spring·servlet·filter·listener
毕设源码-郭学长4 小时前
【开题答辩全过程】以 高校项目团队管理网站为例,包含答辩的问题和答案
java