简体   繁体   中英

Java generics confusion with two generic super-types

I have a (poor man's) either-type in 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);
    }
}

I would like to add a method to join the L or R to an instance of some type T :

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

But Java does not like this generic constraint: T extends L & R . How can I represent this operation in the Java type system?

You can only do this on an Either where the two types are related to the type you want to return. Since this isn't generally the case, you need to do this in a static method (or, at least, some method not on the instance of Either ):

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

The constraint that you are putting on your T here can't work. How is the compiler supposed to know that the L l or R r that you put into your Either object are both L and R at the same time?!

In other words: you want to your result of join() to be Fruit ; than that would require that the "incoming" L l and R r where both Fruits when you created that object. But what happened when you didn't put an Apple and a Banana into your Either, but an Apple and a Scissor? How do you think you could join them under a common supertype?!

You possibly want to describe case when T extends L or R (as it obviouslty doesn extend both of them at the same time). But you can't do such specification in Java.

Do not overcomplicate this case and do just:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM