简体   繁体   中英

Java generic upper bounded wildcard error

I have the following entities in my domain model:

class Point {
    public String details;

    public Point() {
        details = "empty";
    }

    public Point(String details) {
        this.details = details;
    }
}

class BasicPoint<X, Y> extends Point {
    public X x;
    public Y y;

    public BasicPoint() {}

    public BasicPoint(X x, Y y) {
        this.x = x;
        this.y = y;
    }
}

class Collector<T> {
    T elem;

    public void collect(T elem) {
        this.elem = elem;
    }
}

I want to apply operations on data and return that data as Point or BasicPoint, as declared above, but the compiler is complaining with the following error although OUT extends Point:

class Operator<OUT extends Point> {
    public Collector<OUT> operate(Collector<OUT> collector) {

        // compile error, collect(OUT) cannot be applied to BasicPoint<Integer, Integer>
        collector.collect(new BasicPoint<Integer, Integer>(1,2));

        return collector;
    }
}

Main method should look like:

Collector<BasicPoint<Integer, Integer>> c = new Collector<>();
c = new Operator<BasicPoint<Integer, Integer>>().operate(c);
System.out.println(c.elem.getClass() == new BasicPoint<Integer, Integer>().getClass());

Your Operator is generic it cannot apply collect on a BasicPoint , only OUT . You can make your Collector abstract:

abstract class Operator<OUT extends Point> {
    abstract Collector <OUT> operate(Collector<OUT> collector);
}

And a BasicPointOperator will then contain the actual implementation which you want:

class BasicPointOperator extends Operator<BasicPoint<Integer, Integer>> {

    @Override
    Collector<BasicPoint<Integer, Integer>> operate(Collector<BasicPoint<Integer, Integer>> collector) {
        collector.collect(new BasicPoint<Integer, Integer>(1,2));
        return collector;
    }
}

or PointOperator , which is a bit more generic

class PointOperator extends Operator<Point> {

    @Override
    Collector<Point> operate(Collector<Point> collector) {
        collector.collect(new BasicPoint<Integer, Integer>(1,2));
        return collector;
    }
}

The problem is that you can't put things in unless the type parameter is contravariant . Something like that

public Collector<?>  operate(Collector<? super Point> collector) {
    collector.collect(new BasicPoint<Integer, Integer>(1,2));
    collector.collect(new Point());

    return collector;
 }

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