Oct 18, 2017
Java 泛型-泛型类型
泛型类型(Generic Type)是带类型参数的类或接口。下面我们通过 Box 类来论述什么是泛型类型。
简单的 Box
1 | public class Box { |
由于 box 接收或返回一个 Object 对象,你可以传入任何你想要的非基本类型,因此在编译阶段无法判断 box 的使用情况。下面的例子在运行时会发生 ClassCastException
错误。
1 | Box box = new Box(); |
泛型版本的 Box
1 | public class Box<T> { |
可以看到,所有的 Object 都被替换成 T。我们称 T 为类型参数或类型变量,它可以是任何的非基本类型:类、接口、数组、甚至是类型参数。
根据上面的例子,我们可以得出泛型类定义的语法:class name<T1, T2, ..., Tn> {/* ... */}
用尖括号(<>)分割的类型参数,遵循类名。泛型接口的定义和泛型类相似。
类型参数的命名惯例
按照惯例,类型参数的命名是单个大写字母,这样可以很好地区分类型参数和普通类或接口。
最常用的类型参数如下:
- E - Element
- K - Key
- V - Value
- T - Type
- N - Number
- S,U,V etc. - 2nd, 3rd, 4th types
泛型类型的调用和实例化
还是以上面的 Box 为例,Box 的调用和实例化如下:
1 | // 实例化 |
棱形
在 Java SE 7 和 Java SE 7 之后,你可以用一个空的类型参数(一对尖括号:<>)来替换泛型类的构造,只要编译器可以确定或者推断出上下文中的类型参数。这对尖括号叫做棱形。例如,你可以使用下面的语句创建一个 Box 示例:
1 | Box<Integer> integerBox = new Box<>(); |
更多关于棱形和类型推断,请查看 Java 泛型-类型推断。
Type Paramemter 和 Type Argument
Type Parameter 和 Type Argument 在中文上都是叫类型参数,很多开发者容易认为是同一个概念,其实它们是有区别的。在编写代码时,为了创建参数化类型,可以提供类型参数(Type Argument)。因此,Box<T>
中的 T 是一个 Type Paramemter,而 Box<Integer>
的 Integer 是一个 Type Argument。
参数化类型
像 List<String>
这种带类型参数的类型,我们称为参数化类型。泛型的实例化也支持参数化类型。如:
1 | // 实例化 |