例如,我有这些通用类:
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)
会给我编译时错误,因为它希望w
与Foo::printValue
中定义的使用者完全相同,这会导致类型不匹配在DoubleWrapper
中指定的绑定类型NumberWrapper<?, ? extends NumberWrapper>
的{{1}}(NumberWrapper<?, ?>
}和T
之间。
这是我的Eclipse IDE显示的编译错误:
scheduleToPrint