Java泛型(超详细介绍)
- 人工智能
- 2025-08-25 16:00:01

一、泛型
什么是泛型?为什么要使用泛型?
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错。
那参数化类型是什么?
以方法的定义为例,在方法定义时,将方法签名中的形参的数据类型也设置为参数(也可称之为类型参数),在调用该方法时再从外部传入一个具体的数据类型和变量。
泛型的本质是为了将类型参数化, 也就是说在泛型使用过程中,数据类型被设置为一个参数,在使用时再从外部传入一个数据类型;而一旦传入了具体的数据类型后,传入变量(实参)的数据类型如果不匹配,编译器就会直接报错。
这种参数化类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
1.为什么要使用泛型,看下面程序存在的缺陷?User类:
public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void pay(){ System.out.println(this.name + "正在支付。。。"); } } import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 当前程序先不使用泛型,分析存在什么缺点? * 不好看,代码写的比较多。每一次从集合中取出的元素要想访问子类中特有的方法,必须向下转型。 * 大部分都是要写向下转型的。因为Object类中的方法肯定是不够用的。一定会调用子类方法。 */ public class GenericTest01 { public static void main(String[] args) { // 创建集合 Collection c = new ArrayList(); // 创建User类型的对象 User u1 = new User("张三"); User u2 = new User("李四"); User u3 = new User("王五"); // 添加到集合中 c.add(u1); c.add(u2); c.add(u3); // 遍历集合 Iterator it = c.iterator(); while(it.hasNext()){ Object obj = it.next(); if(obj instanceof User) { // 支付 // 这里没有使用泛型机制,那么要想调用pay()方法,必须进行向下转型 User user = (User) obj; user.pay(); } } } } 2.泛型User类:
public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void pay(){ System.out.println(this.name + "正在支付。。。"); } } import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * 使用泛型机制。 */ public class GenericTest02 { public static void main(String[] args) { // 程序编写的时候,是否可以使用泛型,看哪里? // 看帮助文档中有没有“<>”符号。 // 有这个符号的都可以使用泛型。 // 创建一个集合,要求这个集合中只能存放User类型的对象。不能存储其他类型。 //Collection<User> users = new ArrayList<User>(); Collection<User> users = new ArrayList<>(); // 向集合中添加User对象 User u1 = new User("张三"); User u2 = new User("李四"); User u3 = new User("王五"); users.add(u1); users.add(u2); users.add(u3); // 编译器报错,不能添加其他类型,只能添加User类型。 //users.add("abc"); // 遍历集合 Iterator<User> it = users.iterator(); while(it.hasNext()){ User user = it.next(); user.pay(); } } }运行结果:
3.Java7的新特性:钻石表达式< >里面的对象,写前面一个就行
Collection<String> strs = new ArrayList<>(); 4.泛型的擦除与补偿(了解)泛型的作用
编译时类型安全:
在编译阶段检查集合元素的类型,避免运行时出现ClassCastException。
代码可读性:
明确集合中元素的类型,减少类型转换代码。
⑴.泛型擦除(Type Erasure)(子类——>Object)
机制: 编译后擦除:泛型信息在编译后被移除,替换为 Object 类型(或泛型上限类型)。
示例:
List<String> list = new ArrayList<>(); // 编译后变为 List<Object>原因:其本质是为了让JDK1.4和JDK1.5能够兼容同一个类加载器。在JDK1.5版本中,程序编译时期会对集合添加的元素进行安全检查,如果检查完是安全的、没有错误的,那么就意味着添加的元素都属于同一种数据类型,则加载类时就可以把这个泛型擦除掉,将泛型擦除后的类型就是Object类,这样擦除之后的代码就与JDK1.4的代码一致。
运行时无关性:泛型是编译时技术,JVM 不感知泛型。
由于加载类的时候,会默认将类中的泛型擦除为Object类型,所以添加的元素就被转化为Object类型,同时取出的元素也默认为Object类型。而我们获得集合中的元素时,按理说取出的元素应该是Object类型,为什么取出的元素却是实际添加的元素类型呢?
⑵.泛型补偿(Type Compensation)(Object——>子类)
机制: 运行时自动强转:从集合中取出元素时,JVM 根据元素的实际类型隐式执行强制类型转换。
示例:
List<String> list = new ArrayList<>(); list.add("hello"); // 编译后变为 List<Object> String s = list.get(0); // 自动转换为 String,无需手动强转这里又做了一个默认的操作,我们称之为泛型的补偿。在程序运行时,通过获取元素的实际类型进行强转,这就叫做泛型补偿(不必手动实现强制转换)。
获得集合中的元素时,虚拟机会根据获得元素的实际类型进行向下转型(父转子),也就是会恢复获得元素的实际类型,因此我们就无需手动执行向下转型操作,从本质上避免了抛出类型转换异常。
意义:
开发者透明:无需手动写类型转换代码。
避免类型错误:编译时已确保类型安全,运行时不会抛出 ClassCastException。
阶段 泛型擦除 泛型补偿 时间 编译时 运行时 操作 泛型信息替换为Object 隐式执行Object → 实际类型的转换 目的 兼容旧版本,简化 JVM 实现 恢复实际类型,保证代码逻辑正确性 5.泛型的使用:在类上定义泛型⑴.泛型类基本概念
作用:让类可以处理多种数据类型,同时保
Java泛型(超详细介绍)由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Java泛型(超详细介绍)”