Java 中的泛型 (Generic)

泛型 (Generic)

泛型 (Generic),即“参数化类型”,就是允许在定义类、接口、方法时使用类型形参,这个类型形参将在使用时(声明变量、创建对象、调用方法)传入实际的类型参数(类型实参)。

好处

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,可以提高代码的重用率。

规则

1. 使用简练的名字作为类型形参的名字,最好为单个的大写字母,比如 T ;
2. 如果一个泛型类有泛型方法,对于它们的类型形参来说,应避免使用相同的名字;
3. 泛型的类型实参只能是类类型,不能是基本数据类型。

“菱形”语法

在 Java 7 之前,如果使用带泛型的接口、类定义变量时,调用构造器创建对象时,构造器后面必须带泛型,如: List list = new ArrayList();
而从 Java 7 开始,Java 允许在构造器后面不带完整的泛型信息,只需给出一对尖括号即可<>,如:List list = new ArrayList<>();

定义泛型类

具体例子:

Java 中的泛型 (Generic)_第1张图片
Person - class

上面定义了一个带泛型声明的 Person 类,其有一个形式参数为泛型的构造器和一个返回值类型为泛型的 getInfo() 方法,使用 Person 类时就可以为 T 类型形参传入实际的类型参数。

运行结果:

Result

结果分析:

第27行代码的返回结果为 true,这是因为不管为泛型的类型形参传入什么类型实参,它们依然被当成同一个类处理,在内存中也只占一块内存空间。因此,在静态变量、静态方法、静态初始化块的声明和初始化中均不能使用类型形参。另外,instanceof 运算符后也不能使用泛型类。

定义泛型接口

定义泛型接口与定义泛型类道理相同。

定义泛型方法 (Generic Method)

1. 泛型方法,即在声明方法时定义一个或多个类型形参;
2. 语法格式为:
    修饰符  返回值类型 方法名 (参数列表) {}
3. 泛型方法中定义的类型形参只能在该方法里使用。

类型通配符

1. 类型通配符是一个问号 ? , 将问号作为类型实参传给泛型类或泛型接口,如:List (意思是元素类型未知的 List)
2. 在 Java 的集合框架中,对于参数值是未知类型的容器类,只能读取其中元素,不能向其中添加元素,因为编译器无法确定添加的元素的类型和集合中的类型是否兼容,但 null 例外,因为它是所有引用类型的实例。

设定类型通配符的上限

1. 当使用 List 这种形式时,表明这个 List 集合可以是任何泛型 List 的父类,如果我们只希望这个 List 集合代表某一类型的父类,可以考虑设定类型通配符的上限。
2. 设定类型通配符上限的格式为:List
    注:Xxxx表示一个类,此处的 ? 表示未知类型,但是此处的未知类型一定是 Xxxx 的子类或它本身,Xxxx 称为这个通配符的上限(upper bound).
3. 由于编译器无法确定这个受限制的通配符的具体类型,所以不能把 Xxxx 对象及其子类的对象加入到这个泛型集合中,只能读取。

设定类型通配符的下限

设定类型通配符上限的格式为:List
    注:Xxxx表示一个类,此处的 ? 表示未知类型,但是此处的未知类型一定是 Xxxx 的父类或它本身,Xxxx 称为这个通配符的下限(lower bound).

设定类型形参的上限

1. 同设定类型通配符的上限一样,Java运行设定类型形参的上限,用于表示传给该类型形参的实际类型是该上限类型或其子类,如:
    public void drawAll(List shapes){}
    注:问号 ? 表示 Shape 的未知子类,编译器无法确定这个类型是什么,所以无法把任何对象添加到这种集合中
2. 当为需要类型形参设定多个上限时,类上限必须位于第一位,并且最多只有一个,而接口上限数量则没有限制,如:
    public class Student{}

参考资料:

  • Java泛型详解 - Jinuxwu的专栏
  • 《疯狂 Java 讲义 第3版》- 李刚
  • Java总结篇系列:Java泛型 - Windstep

你可能感兴趣的:(Java 中的泛型 (Generic))