我正在尝试实现一个通用的容器。所有可能的项目类共享一个单一的抽象基类,该抽象基类提供对周围容器的访问。
以下代码显示了我最简单的方法:
public class GenericContainerProblem {
public static void main(String[] args) {
Container<SpecificItem> container = new Container<>();
new SpecificItem(container);
}
private static class Container<ItemType extends AbstractItem> {
private final List<ItemType> list = new ArrayList<>();
public Container() {
//
}
protected void addItem(ItemType specificItem) {
list.add(specificItem);
}
}
private static abstract class AbstractItem {
protected final Container<? extends AbstractItem> container;
public AbstractItem(Container<? extends AbstractItem> container) {
this.container = container;
container.addItem(this); // fails *
}
}
private static class SpecificItem extends AbstractItem {
public SpecificItem(Container<SpecificItem> container) {
super(container);
container.addItem(this); // succeeds
}
}
}
*)错误:
The method addItem(capture#3-of ? extends GenericContainer.AbstractItem) in the type GenericContainer.Container<capture#3-of ? extends GenericContainer.AbstractItem> is not applicable for the arguments (GenericContainer.AbstractItem)
由于声明
? extends AbstractItem
可能的类型不匹配,因此无法正常工作。我想我需要一些类型约束来告诉编译器Container<?>
中使用的AbstractItem
类型对this
有效。如何声明/调用
AbstractItem
-类(及其构造函数),使其可以访问有关特定子类的通用容器? 最佳答案
据我所知,您需要使AbstractItem为泛型,以便指定其使用的容器的类型。您还需要在AbstractItem构造函数中使用未经检查的强制转换。
但是,您真的确定要在容器和容器之间建立双向关联吗?也许您应该重新考虑这种设计。
public class GenericContainerProblem {
public static void main(String[] args) {
Container<SpecificItem> container = new Container<>();
new SpecificItem(container);
}
private static class Container<ItemType extends AbstractItem<ItemType>> {
private final List<ItemType> list = new ArrayList<>();
public Container() {
//
}
protected void addItem(ItemType specificItem) {
list.add(specificItem);
}
}
private static abstract class AbstractItem<T extends AbstractItem<T>> {
protected final Container<T> container;
public AbstractItem(Container<T> container) {
this.container = container;
container.addItem((T) this);
}
}
private static class SpecificItem extends AbstractItem<SpecificItem> {
public SpecificItem(Container<SpecificItem> container) {
super(container);
container.addItem(this);
}
}
}