12月25日

泛型的类型参数
泛型的类型参数可以是任何有效的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 = new Box<>();
integerBox.set(10);
System.out.println(integerBox.get());

Box doubleBox = new 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 = new Box<>();
integerBox.set(10);
printBox(integerBox);

Box stringBox = new 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 = new Box<>();
integerBox.set(10);
printNumbers(integerBox);

Box doubleBox = new 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 numberBox = new Box<>();
process(numberBox);
System.out.println(numberBox.get());
泛型的类型擦除
Java的泛型在编译时会被擦除,即编译后的字节码中不包含泛型信息。这意味着泛型类型在运行时无法获取具体的类型参数。例如:

java
Box integerBox = new Box<>();
Box stringBox = new Box<>();
System.out.println(integerBox.getClass() == stringBox.getClass()); // 输出 true
在运行时,integerBox和stringBox的类型都是Box,泛型信息被擦除。
类型擦除的影响
类型擦除导致泛型类型在运行时无法获取具体的类型参数,因此无法在运行时进行类型检查和类型转换。例如,以下代码会编译错误:

java
Box integerBox = new Box<>();
Box stringBox = new Box<>();
if (integerBox instanceof Box) { // 编译错误
// ...
}

桥接方法
为了保持类型安全,编译器会为泛型类生成桥接方法(Bridge Methods)。桥接方法是编译器自动生成的,用于在运行时调用具体的方法。例如:

java
public class Box {
public T get() {
return t;
}
}
编译器会生成一个桥接方法:

java
public Object get();
这个桥接方法在运行时被调用,确保类型安全。

posted @ 2025-01-10 18:41  头发少的文不识  阅读(21)  评论(0)    收藏  举报