是否可以创建类型安全的Java集合,其成员只实现多个接口?

时间:2012-04-02 00:14:05

标签: java generics

如果我有:

interface A{  void a();  }
interface B{  void b();  }

我可以使用这样的通用方法:

class C {
    <T extends A & B> void c(T t) {
        t.a();
        t.b();
    }
}

但我不能像这样拥有一个通用的集合:

class D{
    List<? extends A & B> l;
}

我知道我可以制作一个空接口E,它既可以扩展A又可以B,并且有一个包含E的List ......但我宁愿让我的类只用A和B标记,而不是必须当有更多的A和B可以以2 ^ n种方式组合时,这就更成问题了。

我宁愿能够动态定义一个类型,作为接口的联合,并让集合识别将所有接口实现为该类型实例的对象。

有没有办法在Java中执行此操作?我愿意接受任何类型的工作或破解这一点,以避免创建一个新的界面,并用它标记我的类,这样他们就可以在一个集合中共同生活。或者,如果有人能够为我澄清为什么这是不可能的,那也同样值得赞赏。

2 个答案:

答案 0 :(得分:9)

public class Foo<T extends A & B> {
    private List<T> list;
    //getters, setters, etc.
}

答案 1 :(得分:0)

正如杰弗里也说的那样,你必须参数化你的班级D

class D<T extends A & B> {
    List<T> l;

    /**
     * this is just a method for the sake of example
     */
    public T getSomeMember() {
        return l.iterator().next();
    }
}

通过这种方式,您可以将实际类型T的选择推迟到实际引用D的方法。如果即使在那时该信息也不可用,您也必须使用<T extends A & B>参数化该方法:

private <T extends A & B>
void doSomething() {
    D<T> d = new D<T>();

    T v1 = d.getSomeMember();
    A v2 = d.getSomeMember();
    B v3 = d.getSomeMember();
}

如果某个类中存在类型为D的字段,则该类必须知道extends A & B的实际类型,否则将自身参数化。原则上,您将传播类型参数,直到您知道实际类型。

请注意,对于大型代码,此过程可能无法管理。它也可能导致丑陋的代码,但当然这取决于你对美学的概念。