泛型类、接口和方法本质是将类型作为参数,仅在编译期生效以保障类型安全;泛型类如Box<T>用于容器,需指定引用类型;泛型接口如Repository<T>支持灵活实现;泛型方法如<T> T pickFirst(T,T)可独立复用。

泛型类、泛型接口和泛型方法,本质都是把“类型”当作参数来用,让代码更安全、更通用。它们不是运行时特性,只在编译期起作用——编译器靠它做类型检查、避免强转、提前报错。
泛型类:适用于需要统一管理多种类型数据的容器或业务模型
定义时在类名后加 <T>(或多个如 <K, V>),T 是类型形参,代表将来传入的具体类型。成员变量、方法参数和返回值都可以使用 T。
- 语法示例:public class Box<T> { private T content; public void set(T content) { this.content = content; } public T get() { return content; } }
- 使用时必须指定具体类型:Box<String> stringBox = new Box<>(); 或 Box<Integer> intBox = new Box<>();
- 不能用基本类型(如 int),只能用包装类(Integer)、String、自定义类等引用类型
- 典型场景:集合类(ArrayList<E>)、工具封装类(如响应体 Result<T>)、实体映射类
泛型接口:适用于行为契约需适配不同数据类型的抽象层
接口也可以声明类型参数,实现类可以选择在实现时确定类型,也可以继续保留泛型。
- 语法示例:public interface Repository<T> { T findById(Long id); void save(T entity); }
- 实现方式一(保持泛型):class UserRepository<T> implements Repository<T> { ... } —— 创建对象时再指定类型,如 new UserRepository<User>()
- 实现方式二(固定类型):class UserRepo implements Repository<User> { ... } —— 接口类型被固化,该实现只服务 User
- 典型场景:DAO 层接口、策略回调接口、事件处理器(EventHandler<OrderEvent>)
泛型方法:适用于单个操作逻辑需支持多类型输入/输出的函数级复用
方法自己声明类型参数(写在返回值前),不依赖所在类是否泛型,静态方法也能用。
- 语法示例:public <T> T pickFirst(T a, T b) { return a; } 或 public static <E> void printArray(E[] arr) { ... }
- 调用时通常可省略显式类型(编译器自动推断):String s = pickFirst("a", "b");
- 若上下文无法推断(如 null 参数),需手动指定:Util.<String>pickFirst(null, "b")
- 典型场景:工具方法(Collections.sort())、转换函数(jsonToObject<User>(json))、通用校验逻辑
三者不是互斥关系,常组合使用。比如一个泛型接口由泛型类实现,其中又包含泛型方法。关键在于:哪里需要“类型可变”,就在那里引入泛型参数;什么时候确定类型,就什么时候填入具体类型。不复杂但容易忽略细节。

















