无处生还
76.43M · 2026-04-23
泛型在编码过程中的好处:
public class Holder<T> {
public T convertData(T date) {
return null;
}
}
public <T, E> T fetchData(E e) {
return null;
}
interface ClickListener<V> {}
在 Java 中,上界通配符是 extend。带有上界通配符泛型类如下:
public class Holder<T, L extends Listener> {
public T convertData(T date) {
return null;
}
public L listener;
public L fetchListener() {
return listener;
}
}
interface Listener { }
对应 Kotlin 中的 out,写法如下:
class Holder<T, out L : Listener> {
fun convertData(date: T): T? {
return null
}
private var listener: L? = null
fun fetchListener(): L? {
return listener;
}
}
Java 的泛型是不变的,例如:
public void main(String[] args) {
write(new ArrayList<Object>()); // 报错 !!!! List<Number> ≠ List<Object>
}
void write(List<Number> dest) {
dest.add(1);
dest.add(1.1);
}
如果这么生命 write() 函数就没有问题:
void write(List<? super Number> dest) {
dest.add(1);
dest.add(1.1);
}
这么声明的好处如下:
使用泛型通配符,需要遵守 PECS 原则。Extend 只能读取数据,Super 只能写入数据(可以接收的数据类型是 Object)。
Collections.copy 源码签名如下:
public static <T> void copy(
List<? super T> dest,
List<? extends T> src
)
src:只读,提供 T → extendsdest:只写,接收 T → super泛型擦处是指:在编译的时候使用泛型,在运行的时对类型进行替换。例如:
List<String> list = new ArrayList<>(); // 编译时
List list = new ArrayList(); // 运行时
进行泛型擦除的主要目的,是因为泛型是在1.5才出现,为了确保之前的代码和 JVM 完全兼容。当然擦除也带来了一些问题: