如何解决Either.converge()方法运行时的Java泛型问题
原问题
给定以下精简版Either类(带完整Javadoc的完整版本托管在GitHub):
public final class Either<L, R> { private final Optional<L> left; private final Optional<R> right; public Either(Optional<L> left, Optional<R> right) { if (left.isEmpty() == right.isEmpty()) { throw new IllegalArgumentException("left.isEmpty() must not be equal to right.isEmpty()"); } this.left = left.map(Objects::requireNonNull); this.right = right.map(Objects::requireNonNull);; } public <T> T converge( Function<? super L, ? extends T> leftFunction, Function<? super R, ? extends T> rightFunction ) { Objects.requireNonNull(leftFunction); Objects.requireNonNull(rightFunction); return this.right .<T>map(r -> Objects.requireNonNull(rightFunction.apply(r))) .orElseGet(() -> this.left .map(l -> Objects.requireNonNull(leftFunction.apply(l))) .orElseThrow(() -> new IllegalStateException("should never get here"))); } }
我发现自己反复调用converge(Function.identity(), Function.identity()):
Either<Integer, Integer> either = ...; //... var t = either.converge(Function.identity(), Function.identity());
因此,为了遵循DRY(Don't Repeat Yourself,不重复代码)原则简化客户端代码,我希望添加一个无参的converge()方法,如下所示:
public <T extends L & R> T convergeDesired() { return left.isPresent() ? left.get() : right.get(); }
该方案会引发编译错误,这是因为遇到了Java泛型的限制问题:由于R可能是一个类,这违反了泛型中限制T只能继承一个类(若存在则必须放在首位)的规则。我们无法提前知晓Either是否由两个类组成,或者L是接口而R是类。
下面的临时方案看起来非常脆弱。我想了解是否有可行的方案,能够让它的行为更接近上述定义的convergeDesired()方法。
public <T> Optional<T> convergeHacked() { return this.left.getClass().getTypeParameters()[0].getClass() == this.right.getClass().getTypeParameters()[0].getClass() ? (Optional<T>) (this.left.isPresent() ? left.get() : right.get()) : Optional.empty(); }
内容的提问来源于stack exchange,提问作者chaotic3quilibrium
相关产品推荐
相关产品推荐

