一、概念
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
1. 泛型方法
泛型方法可以接收不同类型的参数的方法。在调用该方法是,可以根据传递的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:
(1) 泛型方法在方法返回类型之前有一个类型参数声明部分"< E >";
(2) 类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开;
一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
(3) 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符;
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
语法:
public static < E > void printArray( E[] e );
有界的类型参数:
可能有时候,你会想限制那些被允许传递到一个类型参数的类型种类范围。
例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。
要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。
语法:
public static <T extends Comparable<T>> T maximum(T x, T y, T z);
2. 泛型类
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。
一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
语法:
public class Box<T>;
3. 类型通配符
(1) 类型通配符一般是使用?代替具体的类型参数。例如 List<?> 在逻辑上是List<String>, List<Integer> 等所有List<具体类型实参>的父类。
语法:
public static void getData(List<?> data);
(2) 类型通配符上限通过形如List来定义,如此定义就是通配符泛型值接受Number及其下层子类类型。
语法:
public static void getUperNumber(List<? extends Number> data);
(3) 类型通配符下限通过形如 List<? super Number>来定义,表示类型只能接受Number及其三层父类类型,如 Object 类型的实例。
<? extends T>和<? super T>的区别:
<? extends T>表示该通配符所代表的类型是T类型的子类。 [上限]
<? super T>表示该通配符所代表的类型是T类型的父类。 [下限]
常用以下字符表示参数类型:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
S、U、V - 2nd、3rd、4th types
二、使用教程
1. 泛型方法
// 泛型方法 printArray
public static <E> void printArray(E[] inputArray) {
// 输出数组元素
for (E element : inputArray) {
System.out.printf("%s ", element);
}
}
有界的泛型方法:
// 比较三个值并返回最大值 参数的类型必须实现了Comparable接口,即必须是可比较的
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // 假设x是初始最大值
if (y.compareTo(max) > 0) {
max = y; //y 更大
}
if (z.compareTo(max) > 0) {
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}
2. 泛型类
public class Box<T> {
private T t; public void add(T t) {
this.t = t;
} public T get() {
return t;
} public static void main(String[] args) {
Box<String> stringBox = new Box<String>();
stringBox.add(new String("陈数"));
// \n是换行符,使光标定位到下一行
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}
3. 类型通配符
public static void getData(List<?> data) {
System.out.println("data :" + data.get(0));
}
有上界的类型通配符:
public static void getUperNumber(List<? extends Number> data) {
System.out.println("data :" + data.get(0));
}
参考: