想象一下通用类MySet,它维护父MySet实例和子MySet实例。这个想法是父母应该能够拥有T的超集,并且孩子可以成为子集。因此,给出以下示例,请考虑以下问题:
class MySet<T> {
MySet<? extends T> child;
void doStuff (Collection<? extends T> args) {
child.doStuff(this, args);
}
}
编辑:修复问题和示例代码以反映真正的问题
现在,孩子通用<T
&gt;可能比父母的<T
&gt;更具限制性,因此父母必须传入集合<X
&gt;其中<X
&gt;符合孩子的<T
&gt;。请记住,此parent-gt;子链可以延长为任意长。是否有任何方法来安排泛型,以便parent.doStuff(...)将编译,即,只能使用它最具限制性的子项的参数调用它?
这意味着java编译器会在parent-gt;子链上向上传递通用信息,以确定doStuff允许的参数是什么,并且我不知道它是否具有该功能。< / p>
唯一的解决方案是确保孩子不能比使用泛型的父母(即MySet <T
&gt;孩子;而不是MySet <? extends T
&gt;)更具限制性,并让孩子比他们的父母在代码的其他地方?
答案 0 :(得分:1)
我可以立即对该问题的部分内容给出否定答案:
有没有办法安排 泛型,以便parent.doStuff(...) 将编译,即只能它 用它的参数调用 最严格的孩子?
这意味着java编译器 会传递所有通用信息 父 - >子链的方式向上 确定允许的参数是什么 doStuff可能是,我不知道 如果它有这种能力。
简单的答案是否定的,因为该链的实际扩展(和类型要求)仅在运行时已知,到那时,有关泛型的任何信息都已通过擦除而丢失。
更进一步,如果你有一个检查类型而不是vanilla泛型,有一个方法可以在链中传递(最严格的)实际类型接受,你可以在运行时进行检查,并提出一个运行时错误,但它永远不会是编译错误。
所以不,除非事先知道(并指定,可能是第二种类型arg)实际的最终类型,否则编译器将无法帮助你。
你能做什么(并且应该做什么)与你刚刚编写的内容(应该编译得很好)保持一致,然后传递一个可能不安全的参数。无论您是自己进行类型检查,还是让JVM引发ClassCastException都是一个选择问题。
答案 1 :(得分:0)
所呈现的代码似乎没有任何意义。
考虑
MySet<String> c = ...;
MySet<Object> p = new MySet<Object>(c);
Collections<Integer> ints = ...;
p.doStuff(ints);
这将打电话给c.doStuff(???, ints)
。 ints
的类型为Collection<Integer>
,但被调用方需要doStuff(Collection<? extends String>)
。