【问题标题】:preserve generics in list elements在列表元素中保留泛型
【发布时间】:2018-01-26 11:23:50
【问题描述】:

我有一个依赖泛型在内部绑定类型的类。

class C<T1, T2 extends T1> {
    T1 e1;
    T2 e2;
    /* stuff */
}

在我的代码中,我知道虽然c.e1c.e2 可能没有相同的类,但c.e2c.e1 类的子类的一个实例。

我需要在这些cs 中创建一个List,并且这些元素不会共享一个公共基类。不过,我想保留List 的每个元素都具有彼此之间有界的属性这一事实。

理想情况下,我想创建一个List&lt;C&lt;?, ? extends ...&gt;&gt;“但是”我不知道任何语法来指定这种行为。 并且使用 List&lt;C&lt;?, ?&gt;&gt; 在我看来,我失去了泛型类型。

进行此收集的正确方法是什么?

【问题讨论】:

    标签: java generics java-7 generic-list


    【解决方案1】:

    由于T2C 的声明中是有界的,即使您使用通配符,您也将始终保留它是T1 的子类型这一事实。即 C 的一个特点是第二个类型参数扩展了第一个。

    所以你可以使用List&lt;C&lt;?, ?&gt;&gt;

    当您尝试将泛型参数绑定到类型变量时,您已经可以看到这是可行的。例如:

    public static <T1, T2> void m(List<C<T1, T2>> list) { ... }
                                             ^^-- Bound mismatch
    

    你需要使用:

    public static <T1, T2 extends T1> void m(List<C<T1, T2>> list) {...}
    

    或者:

    public static <T1> void m(List<C<T1, ? extends T1>> list) {...}
    

    让编译器开心。

    【讨论】:

    • 不幸的是 List 元素不是同质的;我的意思是我需要同时输入c1 = new C&lt;Iface1, Impl1&gt;() c2 = new C&lt;Iface2, Impl2&gt;() ,但是Iface1Iface2 之间没有基类,Impl1Impl2 之间也没有基类。所以我不能有List&lt;C&lt;T1, T2&gt;&gt;,因为没有T1T2 开头
    • @VitoDeTullio 这只是一个例子,关键是你可以使用List&lt;C&lt;?, ?&gt;&gt;
    • 问题是如果我使用List&lt;C&lt;?, ?&gt;&gt; 我会丢失类型。 - 我有另一个方法&lt;T1, T2 extends T1&gt; void m(T1 e1, T2 e2),我无法从列表中提取元素并将它们拆分并将它们传递给方法
    • @VitoDeTullio 也许我误解了你的问题。如果您提供更多有关如何使用列表的示例,这将有所帮助...但是如果您不想丢失类型 根本 您可以使用 2 个列表,1 是List&lt;C&lt;Iface1, Impl1&gt; 和另一个 List&lt;C&lt;Iface2, Impl2&gt;&gt;
    • 问题是我有(可能)不定数量的类型。目前有 7 个接口和 10 个实现。每个组合都有一个列表违背了列表本身的目的
    【解决方案2】:

    我找到了一种将类型约束编码为自定义(非泛型)类型的解决方案。

    所以现在我有这些课程:

    class MainLogic {
        List<TypeHelper<?,?>> elements = new ArrayList<>();
        <T1, T2 extends T1> void addElement(T1 e1, T2 e2) {
            this.elements.add(new TypeHelper<T1,T2>(e1, e2));
        }
        void logic() {
            for (TypeHelper<?, ?> element: elements)
                element.logicHelper(this);
        }
        <T1, T2 extends T1> void logicHelper(T1 e1, T2 e2) {
            // here finally I have the variables constrained
        }
    }
    
    class TypeHelper<T1, T2 extends T1> {
        T1 e1;
        T2 e2;
        void logicHelper(MainLogic ml) {
            ml.logicHelper(e1, e1);
        }
    }
    

    【讨论】:

    • 但是这里的TypeHelper不需要logicHelper,你可以直接调用this.logicHelper(element.e1, element.e2)就可以了。见这里:ideone.com/h4un0O 所以如果TypeHelper 在这里是Ce1 的类型将始终扩展e2 的类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    相关资源
    最近更新 更多