Java泛型(Generics)
泛型的定义是什么?
在 Java Language Specification (JLS) 第 4 章里,对泛型的定义是这样的:Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces, and methods.泛型允许在定义类、接口和方法时,把 类型 作为参数。
通俗解释普通方法/类:
参数是数据(int、String、对象等)。
泛型方法/类:参数可以是“类型”。
也就是说,泛型就是 “把类型当作参数传递给类/接口/方法”。
这样写出来的代码就可以在不同类型上复用,而不需要为每种类型写一份。
三个层面理解泛型
泛型类:class Box<T> { T value; } → 类可以接收类型参数。
泛型接口:interface Repository<T> { T findById(int id); } → 接口可以接收类型参数。
泛型方法:public static <T> void print(T item) → 方法自己可以定义类型参数。
为什么需要泛型?
在泛型出现之前,Java 集合类只能存放 Object 类型的元素。这样有两个问题:类型不安全:你可能往 List 里放 Integer,结果取出来时误以为是 String,运行时报错。需要强制类型转换:取出来的元素必须手动 (类型) 转换,写起来麻烦。 泛型的作用是什么?在编译期检查类型安全避免强制类型转换让代码更通用、可复用
为什么 Java 泛型是伪泛型(类型擦除)?
因为要兼容早期没有泛型的字节码,泛型信息只存在于编译期。
什么时候用 extends,什么时候用 super?
→ 口诀:Producer extends, Consumer super (PECS 原则)如果只从集合里读取数据 → ? extends T如果往集合里写数据 → ? super T
泛型和多态的区别?
泛型:编译期约束,运行时擦除多态:运行时决定方法调用