【问题标题】:Generic collection & wildcard in javajava中的通用集合和通配符
【发布时间】:2011-11-13 20:36:15
【问题描述】:

在以下情况下,我无法理解泛型,请参阅下面的内联 cmets 了解我的问题:

public void exampleMethod() {
    //Intuitively I would expect this to mean that test is set containing objects 
    //that subclass AbstractGroup
    Set<? extends AbstractGroup> test;

    //Yet the compiler complains here and I do not understand why?

    test.add(new AnyAbstractGroupSubGroup());

    //I would guess that a method call such as this at runtime

    test = new HashSet<SubGroupA>()

    //would mean that only objects of subgroupA can be added to the collection, but then
    //what is the point in using the wildcard in the first place?  
}

【问题讨论】:

    标签: java generics collections wildcard


    【解决方案1】:
    //Intuitively I would expect this to mean that test is set containing objects 
    //that subclass AbstractGroup
    Set<? extends AbstractGroup> test;
    

    不,这意味着它是一组特定的?它扩展了 AbstractGroup。你和编译器都不知道那是什么?是的,所以您无法向该 Set 添加任何内容。

    您可以将集合的值分配给 AbstractGroup 类型的变量,但反之则不行。

    相反,你需要这个:

    Set<? super AbstractGroup> test;
    

    这个原则有时被称为PECS,解释得很好in this answer

    【讨论】:

      【解决方案2】:

      Set&lt;? extends AbstractGroup&gt; test;

      这意味着您的集合可以是扩展AbstractGroup 的任何对象的集合,但通常编译器不允许您向该集合添加某些内容(因为它无法判断您是否会添加一个 @ 987654323@ 到 Set&lt;SubGroupA&gt; 等)。

      test = new HashSet&lt;SubGroupA&gt;()

      您的实际集合只包含SubGroupA 类型的对象及其子类。 但是,编译器仍然不知道test 的内容是什么(见上文)。

      通配符的要点是:您可以将任何集合分配给使用AbstractGroup 或子类参数化的变量,从而确保您可以将映射到@ 的所有已经在中的对象强制转换987654329@(编译器检查)。

      如果您想拥有一个可以包含任何 AbstractGroup 对象的集合,请不要使用通配符。

      //this would compile (under the assumption that SubGroupA extends AbstractGroup)
      Set<? extends AbstractGroup> test = new HashSet<SubGroupA>(); 
      
      //this wouldn't compile, since the compiler doesn't know the type of test (it might change at runtime etc.)
      test.add(new SubGroupA());
      
      
      //this wouldn't compile since AbstractGroup and SubGroupA are not the exact same type (hence the wildcard would be needed here)
      Set<AbstractGroup> test = new HashSet<SubGroupA>();
      
      //this would compile
      Set<AbstractGroup> test = new HashSet<AbstractGroup>();
      test.add(new SubGroupA());
      

      【讨论】:

        【解决方案3】:

        这里不需要通配符在你的情况下,说

        Set<AbstractGroup> test;
        

        然后您可以将 AbstractGroup 的任何子类放入集合中。

        此外,您似乎没有在上面的代码中初始化测试。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-28
          • 2011-09-11
          • 2022-12-12
          • 1970-01-01
          • 2014-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多