上界通配符(? extends merchant)用于安全读取多级商户收益,支持distributor、cityagent、provincepartner等子类列表,保障类型兼容与只读汇总。

上界通配符(? extends T)在多级分销系统中不是用来“装数据”的,而是用来安全地“读取统一类型”的——这恰好匹配商户收益模型中「只读汇总、类型兼容、不破坏原有结构」的核心清算场景。
为什么用 ? extends Merchant 收益清单,而不是 List
假设系统存在三类商户:普通分销员(Distributor)、城市代理(CityAgent)、省级合伙人(ProvincePartner),它们都继承自抽象基类 Merchant,且各自有专属字段(如代理等级、区域系数、滑落权重)和共用方法(getSettlementAmount()、getCommissionRate())。
若清算模块写成:
-
void calculate(List<merchant> merchants)</merchant>→ 拒绝传入List<distributor></distributor>,编译失败; -
void calculate(List> merchants)→ 可传入,但无法调用getSettlementAmount()(类型擦除后无方法信息); -
void calculate(List extends Merchant> merchants)→ ✅ 安全通过,且可安全调用所有Merchant声明的方法。
实战精简清算代码:一行提取总分润,不碰具体子类
以下为真实可运行的清算核心逻辑(JDK 17+,无反射、无 instanceof):
public BigDecimal totalCommission(List extends Merchant> merchants) {
return merchants.stream()
.map(Merchant::getSettlementAmount) // 编译期保证:每个元素都能调用该方法
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
说明:
- 无需判断是
Distributor还是ProvincePartner,子类已重写getSettlementAmount(),多态自动生效; - 禁止向该列表
add(...)—— 正是上界通配符的设计本意:保护类型安全,防止误塞不兼容子类(比如把Supplier塞进本应只含Merchant子类的集合); - 若需按等级差异化处理(如省级合伙人额外加权),可配合
instanceof或策略枚举,但「总金额汇总」这一最频繁操作完全无需分支。
与下界通配符(? super T)的关键分工
别混淆用途:
-
List extends Merchant>→ 用于读取:汇总、打印、校验、导出报表; -
List super Distributor>→ 用于写入:例如一个通用收集器,要把新注册的Distributor实例统一存入支持Distributor及其父类的容器(如List<merchant></merchant>或List<object></object>); - 清算模块几乎只读不写,因此上界是唯一合理选择。
避坑提醒:常见误用场景
以下写法看似灵活,实则危险或冗余:
-
List<merchant> list = new ArrayList();</merchant>→ 强制要求所有商户必须是Merchant实例,无法接收List<cityagent></cityagent>,失去泛型多态价值; -
List> rawList = ...; for (Object o : rawList) { if (o instanceof Merchant) {...} }→ 放弃编译期类型检查,退化为运行时弱类型,违背泛型初衷; -
List extends Object>→ 等价于List>,毫无约束力,不能调用任何业务方法,不可用于清算。










