Java泛型是什么?

简介: 本文回顾了作者五年的工作经历,强调了自我学习的重要性,并介绍了Java泛型的基础知识,包括泛型的概念、泛型集合、泛型方法、泛型接口、泛型类及类型擦除等内容,旨在帮助读者理解泛型机制及其在编程中的应用。

1、 文章背景

工作已有五年之久,回望过去,没有在一线城市快节奏下学习成长,只能自己不断在工作中学习进步,最近一直想写写属于自己的文章,记录学习的内容和知识点,当做一次成长。

2、 泛型的概述

摘要:Java泛型是JDK5中引入的一个新特性,其本质是参数化类型‌。

什么是泛型

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错。

Java 1.5 之前没有泛型,通常需要使用强制类型转换的方式将一种数据类型转换为另一种数据类型,这种转换要求开发者对实际参数的类型具有可预知性。对于强制类型转换错误的情况,编译器可能不会提示错误,但是在运行时会出现异常,这是一个安全隐患。

为了解决这一隐患,从 Java 1.5 开始提供了泛型。泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。

3、泛型集合

泛型本质上是提供类型的“类型参数”,也就是参数化类型。我们可以为类、接口或方法指定一个参数类型,通过这个操作限制数据操作的类型,从而保证类型转换的绝对安全。

代码Map<Integer,Book> books=new HashMap<Integer,Book>();创建了一个键类型为 Integer、值类型为 Book 的泛型集合,即指明了该 Map 集合中存放的键必须是 Integer 类型、值必须为 Book 类型,否则编译出错。在获取 Map 集合中的元素时,不需要将books.get(id);获取的值强制转换为 Book 类型,程序会隐式转换。在创建 List 集合时,同样使用了泛型,因此在获取集合中的元素时也不需要将bookList.get(i)代码强制转换为 Book 类型,程序会隐式转换。

4、泛型方法

泛型方法使得该方法能够独立于类而产生变化。如果使用泛型方法可以取代类泛型化,那么就应该只使用泛型方法。另外,对一个 static 的方法而言,无法访问泛型类的类型参数。因此,如果 static 方法需要使用泛型能力,就必须使其成为泛型方法。

  • 4.1 方法中形参类型不确定时
  • 使用类后面定义的泛型。
  • 在方法上定义自己的泛型。

  • 4.2 格式

ini

代码解读

复制代码

[访问权限修饰符][static][final]<类型参数列表> 返回值类型 方法名([形式参数列表]){};

  • 4.3 多个类型参数
  • 泛型方法可以定义多个类型参数。

java

代码解读

复制代码

public static <T, U> void printPair(T first, U second) {
    System.out.println(first + ", " + second);
}
  • 4.4 参数类型约束
  • 可以通过extends关键字对类型参数进行约束,要求类型参数必须是某个类(或接口)的子类(或实现类)。

java

代码解读

复制代码

public static <T extends Number> void printNumber(T num) {
    System.out.println(num);
}

5、泛型接口

泛型接口是Java泛型机制的一部分,它允许在接口定义中使用类型参数,使得实现该接口的类或方法在遵循接口规范的同时,可以处理不同的数据类型。

  • 5.1 格式
  • 泛型接口的定义与泛型类类似,在接口名后面的尖括号<>中指定类型参数。这些类型参数可以在接口的方法签名、返回类型或参数列表中使用。

java

代码解读

复制代码

public interface GenericInterface<T> {

    void someMethod(T t);
    
    T anotherMethod();
}

  • 5.2 实现泛型接口
  • 在实现泛型接口时,可以选择指定类型参数的具体类型,或者将实现类也定义为泛型类,以便推迟类型参数的指定。

java

代码解读

复制代码

// 指定具体类型
public class ConcreteClass implements GenericInterface<String> {
    @Override
    public void someMethod(String s) {
        // 实现方法
    }

    @Override
    public String anotherMethod() {
        // 返回String类型的值
        return "Hello";
    }
}
// 推迟类型参数的指定
public class GenericClass<T> implements GenericInterface<T> {
    @Override
    public void someMethod(T t) {
        // 实现方法
    }

    @Override
    public T anotherMethod() {
        // 返回T类型的值
        return null; // 或者其他T类型的实例
    }
}

  • 5.3 多个类型参数接口
  • 泛型接口可以定义多个类型参数。

java

代码解读

复制代码

public interface MultipleGenericInterface<T, U> {
    T getFirst();
    U getSecond();
}

  • 5.4 类型参数的约束
  • 在接口中定义泛型,并在实现时指定具体类型。

java

代码解读

复制代码

public interface MultipleGenericInterface<T extends Number> {

    // 省略其他方法
}

6、泛型类

泛型类是Java泛型机制的一个重要组成部分,它允许在类定义时使用类型参数,以便类可以处理不同的数据类型。

  • 6.1 格式
  • 泛型类的定义与普通类相似,但在类名后面的尖括号<>中指定了一个或多个类型参数。这些类型参数可以在类的字段、方法参数、返回类型以及方法体内部使用。

java

代码解读

复制代码

public class GenericClass<T> {
    private T value;

    public GenericClass(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

  • 6.2 实例化泛型类
  • 在创建泛型类的实例时,需要指定类型参数的具体类型。

java

代码解读

复制代码

GenericClass<String> stringInstance = new GenericClass<>("Hello");
GenericClass<Integer> integerInstance = new GenericClass<>(123);
  • 6.3 多个类型参数
  • 泛型类可以定义多个类型参数。

java

代码解读

复制代码

public class MultipleGenericClass<T, U> {
    private T first;
    private U second;

    public MultipleGenericClass(T first, U second) {
        this.first = first;
        this.second = second;
    }

    // 省略getter和setter方法
}

  • 6.4 类型参数的约束
  • 与泛型接口类似,泛型类中的类型参数也可以通过extends(对于类)或implements(对于接口)关键字进行约束。例如,要求类型参数继承自某个类或实现某个接口:

java

代码解读

复制代码

public class ConstrainedGenericClass<T extends Number> {
    private T value;

    public ConstrainedGenericClass(T value) {
        this.value = value;
    }

    // 省略其他方法
}

7、类型擦除

泛型的本质是将数据类型参数化,它通过擦除的方式来实现,即编译器会在编译期间擦除代码中的所有泛型语法并相应的做出一些类型转换动作。

换而言之,泛型信息只存在于代码编译阶段,在代码编译结束后,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。也就是说,成功编译过后的 class 文件中不包含任何泛型信息,泛型信息不会进入到运行时阶段。

8、泛型标识

  • 尖括号 <> 中的 泛型标识被称作是类型参数,用于指代任何数据类型。
  • 泛型标识是任意设置的(如果你想可以设置为 Hello都行),Java 常见的泛型标识以及其代表含义如下:

java

代码解读

复制代码

  T :代表一般的任何类。
  E :代表 Element 元素的意思,或者 Exception 异常的意思。
  K :代表 Key 的意思。
  V :代表 Value 的意思,通常与 K 一起配合使用。
  S :代表 Subtype 的意思,文章后面部分会讲解示意。

9、泛型通配符

在Java的泛型机制中,通配符(wildcard)是一种特殊的类型参数,它用于表示未知的类型。泛型通配符主要用于泛型方法的定义中,以及作为泛型类型和泛型方法之间的桥梁,增加代码的灵活性。以下是关于泛型通配符的关键点:

  • 问号(?)
    问号(?)是泛型通配符的基本符号,它表示未知的类型。在泛型方法中,可以使用问号来代替具体的类型参数。
  • 上限通配符(? extends T)
    上限通配符表示未知的类型是T类型或T类型的子类。它用于限制泛型类型的上界,确保泛型方法或泛型集合中的元素是T类型或其子类类型。
    例如,List<? extends Number>表示一个包含Number或其子类(如IntegerDouble等)的列表。
  • 下限通配符(? super T)
    下限通配符表示未知的类型是T类型或T类型的父类。它用于限制泛型类型的下界,允许泛型方法或泛型集合添加T类型或其子类类型的元素,但读取时只能保证是T类型的父类。
    例如,List<? super Integer>表示一个可以包含Integer或其父类(如NumberObject等)的列表,但可以安全地向其中添加Integer类型的元素。


转载来源:https://juejin.cn/post/7428997298196447270

相关文章
|
4天前
|
SQL 人工智能 安全
【灵码助力安全1】——利用通义灵码辅助快速代码审计的最佳实践
本文介绍了作者在数据安全比赛中遇到的一个开源框架的代码审计过程。作者使用了多种工具,特别是“通义灵码”,帮助发现了多个高危漏洞,包括路径遍历、文件上传、目录删除、SQL注入和XSS漏洞。文章详细描述了如何利用这些工具进行漏洞定位和验证,并分享了使用“通义灵码”的心得和体验。最后,作者总结了AI在代码审计中的优势和不足,并展望了未来的发展方向。
|
13天前
|
存储 弹性计算 人工智能
阿里云Alex Chen:普惠计算服务,助力企业创新
本文整理自阿里云弹性计算产品线、存储产品线产品负责人陈起鲲(Alex Chen)在2024云栖大会「弹性计算专场-普惠计算服务,助力企业创新」中的分享。在演讲中,他分享了阿里云弹性计算,如何帮助千行百业的客户在多样化的业务环境和不同的计算能力需求下,实现了成本降低和效率提升的实际案例。同时,基于全面升级的CIPU2.0技术,弹性计算全线产品的性能、稳定性等关键指标得到了全面升级。此外,他还宣布了弹性计算包括:通用计算、加速计算和容器计算的全新产品家族,旨在加速AI与云计算的融合,推动客户的业务创新。
|
11天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
18天前
|
存储 人工智能 缓存
AI助理直击要害,从繁复中提炼精华——使用CDN加速访问OSS存储的图片
本案例介绍如何利用AI助理快速实现OSS存储的图片接入CDN,以加速图片访问。通过AI助理提炼关键操作步骤,避免在复杂文档中寻找解决方案。主要步骤包括开通CDN、添加加速域名、配置CNAME等。实测显示,接入CDN后图片加载时间显著缩短,验证了加速效果。此方法大幅提高了操作效率,降低了学习成本。
3096 10
|
13天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1578 12
|
5天前
|
人工智能 关系型数据库 Serverless
1024,致开发者们——希望和你一起用技术人独有的方式,庆祝你的主场
阿里云开发者社区推出“1024·云上见”程序员节专题活动,包括云上实操、开发者测评和征文三个分会场,提供14个实操活动、3个解决方案、3 个产品方案的测评及征文比赛,旨在帮助开发者提升技能、分享经验,共筑技术梦想。
772 102
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
18天前
|
人工智能 Serverless API
AI助理精准匹配,为您推荐方案——如何快速在网站上增加一个AI助手
通过向AI助理提问的方式,生成一个技术方案:在网站上增加一个AI助手,提供7*24的全天候服务,即时回答用户的问题和解决他们可能遇到的问题,无需等待人工客服上班,显著提升用户体验。
1519 9
|
6天前
|
SQL 存储 人工智能
【产品升级】Dataphin V4.3重大升级:AI“弄潮儿”,数据资产智能化
DataAgent如何助理业务和研发成为业务参谋?如何快速低成本的创建行业数据分类标准?如何管控数据源表的访问权限?如何满足企业安全审计需求?
388 0
【产品升级】Dataphin V4.3重大升级:AI“弄潮儿”,数据资产智能化
|
3天前
|
人工智能 自然语言处理 程序员
提交通义灵码创新实践文章,重磅好礼只等你来!
通义灵码创新实践征集赛正式开启,发布征文有机会获得重磅好礼+流量福利,快来参加吧!
212 7