wrapper 应定义为泛型类 public class wrapper,而非使用通配符;对外只读时返回 wrapper

要编写一个通用、类型安全且灵活的统一返回值 Wrapper,核心是用好泛型上限(? extends T)和下限(? super T),并严格遵循 PECS 原则:Producer(生产者)用 extends,Consumer(消费者)用 super。Wrapper 本身不直接参与读写集合,但它的设计会影响外部如何安全地获取数据或注入数据——尤其是当它被用于 API 响应、DTO 封装或泛型工具方法时。
Wrapper 类定义应使用具体类型参数 T,而非通配符
Wrapper 是一个“容器类”,不是集合操作接口,所以不要在类声明里用 ? extends 或 ? super。正确做法是定义为泛型类:
- public class Wrapper
{ private T data; private String code; private String msg; ... } - 这样能保留类型信息,支持编译期检查,也方便后续扩展(如添加泛型方法)
- 通配符只出现在方法参数或变量声明中,比如接收或返回 Wrapper 的场景
对外提供“只读”能力时,用 ? extends T(Producer 场景)
当其他模块需要从 Wrapper 中安全读取 data,且不关心具体子类型时,方法签名应返回上界通配符:
-
public static
Wrapper extends T> success(T data) { ... } —— 返回值允许调用方按需向上转型(如Wrapper extends Number>可接Integer或Double) - public U getDataAs() { return (U) data; } —— 提供类型安全的向下转型入口(需谨慎,配合 instanceof 或 Class 参数更稳妥)
- 禁止在
Wrapper extends T>引用上调用setData(...),因为编译器无法确认具体子类型,写入会破坏类型安全
对外提供“可写入”能力时,用 ? super T(Consumer 场景)
当 Wrapper 要作为目标容器接收多种子类型的数据(例如批量构建响应),方法参数应使用下界:
- public static
void fillData(Wrapper super T> wrapper, T value) { wrapper.setData(value); } - 这样传入
Wrapper<object></object>、Wrapper<number></number>甚至Wrapper<integer></integer>都合法,只要其类型是T的超类 - 但注意:此时
wrapper.getData()只能声明为Object(或对应超类),不能保证是T,读取需额外转换
搭配函数式接口增强表达力(如 Supplier/Consumer)
Wrapper 常与 Java 8+ 函数式接口协同使用,天然契合 PECS:
-
public static
Wrapper —— Supplier 是 Producer,内部 get() 返回 T,符合of(Supplier supplier) { return new Wrapper(supplier.get()); } extends语义 -
public
Wrapper —— Function 的输入是 Consumer(可用map(Function mapper) { return new Wrapper(mapper.apply(data)); } ? super T),输出是 Producer(可用? extends R),但 Wrapper 自身仍保持具体泛型 T/R - 避免把 Wrapper extends T> 直接传给 Consumer
>,类型不匹配;应改用 Consumer > 或重载方法











