什么是泛型
怎么使用泛型
泛型方法
泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
|
public <T> T doSth(T t){ } |
|---|
泛型方法的规则:
-
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前。
-
每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
-
类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
-
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(int不行,Integer可以)。
泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
|
public class Pair<K, V> implements Serializable{ } |
|---|
编译器如何处理泛型
主流的编译器有2种处理泛型的方式:code specialization 和 code sharing。- Code specialization。在实例化一个泛型类或泛型方法时都产生一份新的目标代码(字节码or二进制代码)。例如,针对一个泛型list,可能需要 针对string,integer,float产生List<String>, List<Integer>, List<Float>。
- Code sharing。对每个泛型类只生成唯一的一份目标代码;该泛型类的所有实例都映射到这份目标代码上,在需要的时候执行类型检查和类型转换。
Code specialization 会为每个类型都产生一份执行代码,浪费空间 ,Java采用code sharing的方式来处理泛型。
类型擦除
- 检查代码中的泛型类型
- 将所有泛型参数用它们的原始类型替换,例如:Object是最顶端的原始类型。
- 编译代码。
那么如何指定泛型的原始类型?
|
public class Pair<K extends Integer, V extends Serializable>{ } |
|---|
上面的Pair泛型类就指定了参数的原始类型,K参数是Integer类型的,V参数是Number类型的。
问题来了,Serializable是接口,为什么是使用extends而不是implements? 这里的extends是用来做类型范围限制的,不是用于实现继承的特性。
extends A 表示泛型参数必须是A的子孙类,比如extends Number, 那么传入的泛型必须是Number的子类,比如Integer, Float等等
super A 表示泛型参数必须是A的父类, 比如super Integer, 那么传入的泛型必须是Integer的父类,比如Number, Object等
本文详细介绍了Java泛型的概念,包括其基本定义、如何在方法和类中使用泛型,以及编译器处理泛型的方式。此外,还讲解了类型擦除的概念及其实现原理。
2488

被折叠的 条评论
为什么被折叠?



