在通用字段中绑定的通配符

时间:2018-03-28 08:25:06

标签: java generics

例如,我有这些通用类:

class Base<A, B extends Base<?, B>> {}
class SubA extends Base<String, SubA> {} // B = own type
class SubB extends Base<String, SubB> {} // B = own type
class SubC extends Base<String, SubA> {} // B != own type

问题出现了:如何存储(作为类字段/变量){em>特定 Base个对象的子类列表,以便B类型是子类类型(即仅允许List<SubA> List<SubB>但不允许List<SubC>)?

等效方法是:

public <T extends Base<?, T>> List<T> getList() {}

但是,无法在那里声明具有T的变量。我该怎么办呢?

修改

(编辑2:我修复了示例代码,因为我在编写没有IDE的时候犯了一些错误)

在阅读了Andy的评论之后,我认为这个例子并非真的准确地表达了我所面临的问题。我将给出一个更准确的例子(虽然这个例子可能看起来不是一个理智的想法)。

abstract class Wrapper<T, W extends Wrapper<T, W>> {
    public abstract W wrap(T original);
    public abstract T unwrap(W wrapper);
}
abstract class NumberWrapper<T extends Number, W extends NumberWrapper<T, W> extends Wrapper<T, W> {
    public final Number getNumber() {
        return unwrap();
    }
}
class IntegerWrapper extends NumberWrapper<Integer, IntegerWrapper> {}
class DoubleWrapper extends NumberWrapper<Double, DoubleWrapper> {}
class LongWrapper extends NumberWrapper<Long, LongWrapper> {}

abstract class ValuePrinter<T> {
    public abstract void printValue(T value);
}

class Foo {
    private ValuePrinter<NumberWrapper<?, ?>> printer = new ValuePrinter<NumberWrapper<?, ?>>() {
        @Override public void printValue(NumberWrapper<?, ?> value) {
            Number num = value.getNumber();
            System.out.println(num); // Don't ask why this is done
        }
    };

    public ValuePrinter<NumberWrapper<?, ?>> getPrinter() { return printer; }
}

/**
 * A scheduler that prints value once every 5 seconds.
 */
static class Scheduler<T> {
    private LinkedList<T> printingQueue;
    private final ValuePrinter<T> printer;

    public Scheduler(ValuePrinter<T> printer) {
        this.printer = printer;
    }

    public void scheduleToPrint(List<T> toPrint) {
        printingQueue.addAll(toPrint);
        startIfNotStarted();
    }
}

class Test {
    private List<DoubleWrapper> doubleWrappers;
    private List<IntegerWrapper> intWrappers;
    private Foo foo;

    public void scheduledPrintDoubles() {
        new Scheduler<>().scheduleToPrint(doubleWrappers, foo.getPrinter()); // Compile error
    }
}

这个新例子可能没有意义,但它描述了我面临的问题。我已将printer声明为ValuePrinter<NumberWrapper<?, ?>>,因为这是最方便的。

但是,调用Scheduler.getInstance().scheduleToPrint(w, Foo::printValue)会给我编译时错误,因为它希望wFoo::printValue中定义的使用者完全相同,这会导致类型不匹配在DoubleWrapper中指定的绑定类型NumberWrapper<?, ? extends NumberWrapper>的{​​{1}}(NumberWrapper<?, ?>}和T之间。

这是我的Eclipse IDE显示的编译错误:

scheduleToPrint

0 个答案:

没有答案