泛型的类型参数
泛型的类型参数可以是任何有效的Java类型,但不能是基本数据类型。可以使用类、接口或自定义类型作为类型参数。
类型参数的限制
可以使用extends关键字对类型参数进行限制,表示类型参数必须是某个类的子类或实现某个接口的类。例如:
java
public class Box
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
在这个例子中,Box类的类型参数T必须是Number类的子类,如Integer、Double等:
java
Box
integerBox.set(10);
System.out.println(integerBox.get());
Box
doubleBox.set(3.14);
System.out.println(doubleBox.get());
多个类型参数
可以同时使用多个类型参数,每个类型参数用逗号分隔。例如:
java
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
可以创建不同类型的Pair对象:
java
Pair<String, Integer> pair1 = new Pair<>("One", 1);
System.out.println(pair1.getKey() + ": " + pair1.getValue());
Pair<String, Double> pair2 = new Pair<>("Pi", 3.14);
System.out.println(pair2.getKey() + ": " + pair2.getValue());
泛型的通配符
通配符(?)用于表示未知类型,可以用于泛型方法的参数或返回值。通配符可以分为无界通配符、有界通配符和通配符的上下界。
无界通配符(?)
无界通配符表示未知类型,可以匹配任何类型。例如:
java
public static void printBox(Box<?> box) {
System.out.println(box.get());
}
可以使用任何类型的Box对象调用printBox方法:
java
Box
integerBox.set(10);
printBox(integerBox);
Box
stringBox.set("Hello");
printBox(stringBox);
有界通配符(? extends T 和 ? super T)
有界通配符可以对通配符的类型进行限制。? extends T表示类型参数是T的子类,? super T表示类型参数是T的父类。例如:
java
public static void printNumbers(Box<? extends Number> box) {
System.out.println(box.get());
}
可以使用Number的子类类型的Box对象调用printNumbers方法:
java
Box
integerBox.set(10);
printNumbers(integerBox);
Box
doubleBox.set(3.14);
printNumbers(doubleBox);
通配符的上下界
通配符的上下界可以同时使用,表示类型参数在某个范围内。例如:
java
public static void process(Box<? super Integer> box) {
box.set(10);
Number n = box.get();
}
可以使用Integer的父类类型的Box对象调用process方法:
java
Box
process(numberBox);
System.out.println(numberBox.get());
泛型的类型擦除
Java的泛型在编译时会被擦除,即编译后的字节码中不包含泛型信息。这意味着泛型类型在运行时无法获取具体的类型参数。例如:
java
Box
Box
System.out.println(integerBox.getClass() == stringBox.getClass()); // 输出 true
在运行时,integerBox和stringBox的类型都是Box,泛型信息被擦除。
类型擦除的影响
类型擦除导致泛型类型在运行时无法获取具体的类型参数,因此无法在运行时进行类型检查和类型转换。例如,以下代码会编译错误:
java
Box
Box
if (integerBox instanceof Box
// ...
}
桥接方法
为了保持类型安全,编译器会为泛型类生成桥接方法(Bridge Methods)。桥接方法是编译器自动生成的,用于在运行时调用具体的方法。例如:
java
public class Box
public T get() {
return t;
}
}
编译器会生成一个桥接方法:
java
public Object get();
这个桥接方法在运行时被调用,确保类型安全。