Java中如何表示不相交联合类型并限制实现类的范围?
方案1:Java 16+ 密封类(最优解)
Java 16引入的sealed(密封)语法就是专门为这类「固定子类数量的不相交联合类型」设计的,完美解决你提到的两个痛点:既限制了仅允许指定类型实现接口,也大幅简化了模式匹配的代码,不需要再写冗长的访问者实现。
示例代码如下:
// permits关键字明确指定仅允许Cash、CreditCard两个类实现该接口,外部类无法自定义实现 public sealed interface PaymentMethod permits Cash, CreditCard {} // 实现类声明为final,禁止再被继承扩展 public final class Cash implements PaymentMethod {} public final class CreditCard implements PaymentMethod { private final String accountNum; public CreditCard(String accountNum) { this.accountNum = accountNum; } public String getAccountNum() { return accountNum; } }
如果使用Java 17及以上版本,还可以配合switch模式匹配直接做分支判断,编译器会自动检查所有分支是否覆盖,漏写会直接触发编译错误:
public String getPaymentInfo(PaymentMethod method) { return switch (method) { case Cash cash -> "现金支付"; case CreditCard card -> String.format("信用卡支付,卡号:%s", card.getAccountNum()); }; }
方案2:Java 8~15 兼容方案
如果你的项目暂时无法升级到Java 16以上,可以用「私有构造抽象类+内部静态子类」的方式实现相同的限制效果:抽象类的构造函数设为私有后,只有同一个类内部的子类可以调用父类构造,外部类无法继承该抽象类,自然也不能自定义实现。
示例代码如下:
import java.util.function.Function; public abstract class PaymentMethod { // 私有构造,禁止外部类继承 private PaymentMethod() {} // 提供匹配方法,替代访问者模式,使用更简洁 public abstract <R> R match( Function<Cash, R> onCash, Function<CreditCard, R> onCreditCard ); public static final class Cash extends PaymentMethod { @Override public <R> R match(Function<Cash, R> onCash, Function<CreditCard, R> onCreditCard) { return onCash.apply(this); } } public static final class CreditCard extends PaymentMethod { private final String accountNum; public CreditCard(String accountNum) { this.accountNum = accountNum; } public String getAccountNum() { return accountNum; } @Override public <R> R match(Function<Cash, R> onCash, Function<CreditCard, R> onCreditCard) { return onCreditCard.apply(this); } } }
使用时只需传入两个分支的处理逻辑即可,不需要额外实现访问者接口:
String info = paymentMethod.match( cash -> "现金支付", card -> String.format("信用卡支付,卡号:%s", card.getAccountNum()) );
内容的提问来源于stack exchange,提问作者TJ Mazeika
相关产品推荐
相关产品推荐

