如果我有:
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中执行此操作?我愿意接受任何类型的工作或破解这一点,以避免创建一个新的界面,并用它标记我的类,这样他们就可以在一个集合中共同生活。或者,如果有人能够为我澄清为什么这是不可能的,那也同样值得赞赏。
答案 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
的实际类型,否则将自身参数化。原则上,您将传播类型参数,直到您知道实际类型。
请注意,对于大型代码,此过程可能无法管理。它也可能导致丑陋的代码,但当然这取决于你对美学的概念。