Java泛型混淆了两种通用的超类型

时间:2017-02-13 10:21:57

标签: java generics

我有一个(穷人)在Java中输入任何类型:

public final class Either<L, R> {

    final boolean isLeft;
    final L l;
    final R r;

    private Either(final boolean isLeft, final L l, final R r) {
        this.isLeft = isLeft;
        this.l = l;
        this.r = r;
    }

    // map, right-projection, left-projection, etc.  

    public static <L, R> Either<L, R> left(final L l) {
        return new Either(true, l, null);
    }

    public static <L, R> Either<L, R> right(final R r) {
        return new Either(false, null, r);
    }
}

我想添加一个方法将L或R连接到某种类型T的实例:

    public <T extends L & R> T join() {
        return isLeft ? (T)l : (T)r;
    }

但Java不喜欢这种通用约束:T extends L & R。如何在Java类型系统中表示此操作?

3 个答案:

答案 0 :(得分:6)

您只能在Either上执行此操作,其中两种类型与您要返回的类型相关。由于通常情况并非如此,因此您需要在静态方法中执行此操作(或者,至少某些方法不在Either的实例上):

static <T> T join(Either<? extends T, ? extends T> either) {
  return either.isLeft ? either.l : either.r;
}

答案 1 :(得分:0)

您在这里T施加的约束无效。编译器应该如何知道你放入Either对象的L l或R r同时 L和R?!

换句话说:您希望join()的结果是 Fruit ;比那更需要“传入”L l和R r,当你创建那个对象时,它们都是Fruit。但是当你没有将Apple和香蕉放入你的Either,而是Apple和Scissor时会发生什么?您认为如何以共同的超类型加入他们?!

答案 2 :(得分:0)

您可能想要描述T扩展L R时的情况(因为它很明显并没有同时扩展它们)。但是你不能在Java中做这样的规范。

不要过度复杂化这种情况,只做:

public <T> T join() {
    return isLeft ? (T)l : (T)r;
}