说说java的泛型机制是怎样的

雨强酱_6344

雨强酱_6344

2021-01-27

2581人浏览

转载

面试官:说一下java的泛型机制是怎样的。

(学习视频分享:java视频教程)

精简版回答

Java在开发时,通过使用菱形语法,使一个类、接口或者方法具有接受泛指的一群类作为参数,泛指的类最终由尖括号里的规则所限定,泛指类通常用大写字母表示,一般用字母T,后期经过Java编译器编译,泛型将被擦除,根据具体使用的类,替换泛型,生成class字节码,所以泛型是对Jvm透明的。

豪华版回答

泛型于JDK1.5正式引入

Java引入泛型背景

Java集合是允许放入多种类型的,例如

    List list=new ArrayList();
    list.add("String");
    list.add(1024);

这在JDK1.5之前是常见的使用方式,即便放在今天的JDK下,也是允许的,那么类似于这种集合的使用方式,就会带来一些问题,就是集合中究竟放了哪些类型,恐怕只有创建集合的人才知道,其他调用者,根本无法确定,这样在大型项目里,极易出现问题,调用者强转集合里的某个对象,一旦类型错误,就会报错,这种错在当时编译阶段是无法发现的,只有运行时才被发现,为了解决类似问题,JDK引入了泛型。

泛型类型

引入泛型后,从而可以在编译阶段,检查类型是否符合要求,很大程度上,杜绝了盲目的类型转换。 泛型主要工作在编译器,编译后,JVM运行时,是无法感知泛型的。 泛型分为普通泛型和通配泛型。

1.普通泛型

JavaScript 测试模式
JavaScript 测试模式

使用 Jest、Vitest 和 Testing Library 实施全面的测试策略,包括单元测试、集成测试和端到端测试,涵盖模拟、测试夹具和测试驱动开发。在编

下载

这类泛型顾名思义,就是支持调用时传入任意类型,但是调用时,等号左右俩边泛型必须一致。JDK1.7右侧菱形可以省略。

class Test<t>{...} //声明时
Test<integer> test = new Test<integer>(); //调用时
Test<integer> test = new Test(); //1.7调用时</integer></integer></integer></t>

3.界限泛型

>//无界泛型,任意类型都匹配
<t>//有界泛型 - 继承自某父类
<t>//有界泛型 - 实现某接口
<t>//有界泛型 - 多重边界
<t>//有界泛型 - 指定类父类</t></t></t></t>

泛型擦除

刚才说到,泛型只在写代码时和编译时起作用,而Jvm加载class运行时是无感透明的,是因为编译器编译时将泛型擦除了,简单不严谨的说就是:把类或方法上的那个尖括号干掉了,根据尖括号里的规则换成具体的类,所以Jvm运行时根本不知道这段代码里之前有过泛型,这样做是为了兼容,前面说到泛型是JDK1.5才引入的,这样,即便引入泛型,现有的Jvm也不需要大改,只需要改一下编译器即可,对于这种编译器能感知的语法,而虚拟机无法感知的,人们把这种语法称作语法糖(suger),编译器经过 脱糖(Desuger) 后,拿到干货,交给虚拟机去执行。

(图文教程推荐:java入门教程)

泛型擦除机制

//Pair的泛型
public class Pair<t> {

    private T mFirst;
    private T mSecond;

    public T getmFirst() {
        return mFirst;
    }

    public void setmFirst(T mFirst) {
        this.mFirst = mFirst;
    }

    public T getmSecond() {
        return mSecond;
    }

    public void setmSecond(T mSecond) {
        this.mSecond = mSecond;
    }
}

//Pair的原始类型
//无论何时定义一个泛型类型,都会自动提供一个相应的 原始类型
public class Pair {

    private Object mFirst;
    private Object mSecond;

    public Object getFirst() {
        return mFirst;
    }

    public void setFirst(Object mFirst) {
        this.mFirst = mFirst;
    }

    public Object getSecond() {
        return mSecond;
    }

    public void setmSecond(Object mSecond) {
        this.mSecond = mSecond;
    }
}

//如果调用Pair<t>编译擦除后得到如下=
class Pair{
    private String mFirst;
    private String mSecond;
    ...
}</t></t>

当泛型作为方法的入参时,擦除后换成通配泛型的下界,例如add方法

public static void insertElements(List super A> list){
    //Add进来的都是层级“小于等于”A的,也就是下界
    list.add(new A());
    list.add(new B());
    list.add(new C());
}

当泛型作为方法的回参时,擦除后换成通配泛型的上界,例如get方法

public void processElements(List extends A> elements){
   //for循环挨个get list 里的数据,都当做A,也就是都当做上界
   for(A a : elements){
      System.out.println(a.getValue());
   }
}

对于泛型的类型擦除说再多,看再多博客,不如官方定义准确,放一段Oracle官方对于类型擦除的文档

Type Erasure
Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.Insert type casts if necessary to preserve type safety.Generate bridge methods to preserve polymorphism in extended generic types.Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.

更多面试题请点击:java面试题及答案

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

2026.11.12

40

15

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

2026.11.12

40

15

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

2026.11.12

20

15

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

2026.11.06

140

12

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

2026.11.06

100

13

Postman接口请求发送教程
Postman接口请求发送教程

详细介绍Postman接口请求的创建与发送方法,涵盖GET和POST请求、URL配置、请求参数、Headers请求头、Body请求体设置以及响应结果查看,帮助用户掌握Postman接口请求的完整操作流程。

2026.11.06

100

10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

2026.11.05

80

12

DBeaver安全防护教程大全
DBeaver安全防护教程大全

DBeaver安全防护专题,围绕数据库连接安全、账号密码保护和访问权限管理展开,整理SSL/TLS加密连接、SSH隧道、数据库凭据保存及证书验证等配置方法,同时介绍敏感信息保护、远程连接风险和高权限账号使用等注意事项,帮助用户提高数据库日常管理的安全性。

2026.11.05

80

12

DBeaver连接创建与配置教程
DBeaver连接创建与配置教程

本专题聚焦DBeaver数据库连接配置与管理,覆盖从新建连接、选择数据库类型到填写连接参数和验证连接的完整流程。针对MySQL、PostgreSQL、SQL Server等常见数据库,整理相应的连接设置方法,并提供驱动缺失、认证失败和连接异常等问题的排查方向。

2026.11.04

80

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习