复杂的泛型组合

时间:2009-03-31 19:01:52

标签: java generics

想象一下通用类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;)更具限制性,并让孩子比他们的父母在代码的其他地方?

2 个答案:

答案 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>)