1. 泛型类
泛型类是指在类定义时使用类型参数来指定类的类型。这样可以在类的内部使用这些类型参数来定义字段、方法的返回类型和参数类型。
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
在这个例子中,Box 类使用了一个类型参数 T,可以在创建 Box 对象时指定具体的类型。
Box<Integer> integerBox = new Box<>();
integerBox.set(10);
Integer value = integerBox.get();
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String message = stringBox.get();
2. 泛型接口
泛型接口与泛型类类似,允许在接口定义时使用类型参数。
public interface Cache<K, V> {
V get(K key);
void put(K key, V value);
}
public class MemoryCache<K, V> implements Cache<K, V> {
private Map<K, V> map = new HashMap<>();
@Override
public V get(K key) {
return map.get(key);
}
@Override
public void put(K key, V value) {
map.put(key, value);
}
}
在这个例子中,Cache 接口使用了两个类型参数 K 和 V,分别表示键和值的类型。MemoryCache 类实现了 Cache 接口,并使用了这些类型参数。
Cache<String, Integer> cache = new MemoryCache<>();
cache.put("one", 1);
Integer number = cache.get("one");
3. 泛型方法
泛型方法是指在方法定义时使用类型参数。这样可以在方法内部使用这些类型参数来定义方法的返回类型和参数类型。
public class Util {
public static <T> T getFirst(T[] array) {
if (array == null || array.length == 0) {
return null;
}
return array[0];
}
}
在这个例子中,getFirst 方法使用了一个类型参数 T,可以在调用方法时指定具体的类型。
Integer[] intArray = {1, 2, 3};
Integer firstInt = Util.getFirst(intArray);
String[] stringArray = {"Hello", "World"};
String firstString = Util.getFirst(stringArray);
4. 类型通配符
类型通配符 ? 用于表示未知类型,可以用于方法参数和返回类型,以提高代码的灵活性。
无界通配符:? 表示任意类型。
public void printList(List<?> list) {
for (Object elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
}
有界通配符:
上界通配符:? extends T 表示类型参数是 T 的子类型。
public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list) {
s += n.doubleValue();
}
return s;
}
下界通配符:? super T 表示类型参数是 T 的父类型。
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
5. 泛型的类型擦除
Java 泛型在编译时会被擦除,即编译后的字节码中不包含泛型信息。这意味着在运行时,泛型类型参数会被替换为它们的上界(如果有上界)或 Object(如果没有上界)。
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
编译后,Box 类的字节码中 T 会被替换为 Object:
public class Box {
private Object t;
public void set(Object t) {
this.t = t;
}
public Object get() {
return t;
}
}
6. 泛型的限制
不能使用基本数据类型:泛型只能使用对象类型,不能使用基本数据类型。例如,不能创建 Box,但可以创建 Box。
类型参数不能是 final 类型:不能使用 final 类型作为类型参数。
静态上下文中不能使用类型参数:不能在静态方法或静态初始化块中使用类的类型参数。
类型参数不能是异常类型:不能使用异常类型作为类型参数。