我正在尝试实现一个通用的容器。所有可能的项目类共享一个单一的抽象基类,该抽象基类提供对周围容器的访问。

以下代码显示了我最简单的方法:

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);
        }
    }

}

07-28 00:36