【问题标题】:Generic: ArrayList of ? Extends ISomeInterface in Java通用:ArrayList 的?在 Java 中扩展 ISomeInterface
【发布时间】:2011-12-10 21:17:14
【问题描述】:

我在下面的代码中遇到了一些问题。

public ArrayList<? extends IEvent> getEventsByDateRange(DateTime minStartTime,  DateTime minEndTime) 
{
    ArrayList<? extends IEvent> returnedEvents = new ArrayList<GoogleEvent>();
    returnedEvents.add(new GoogleEvent());
    return (returnedEvents);
}

这会为“returnedEvents.add(new GoogleEvent()); line of code”返回以下编译错误:

类型中的方法add(capture#1-of ? extends IEvent) ArrayList 不适用于 参数(GoogleEvent)

GoogleEvent的声明如下:

public class GoogleEvent implements IEvent {...}

我知道在 Java 中使用泛型有一些棘手的部分,因此是通配符,但我似乎无法弄清楚这一点。

谢谢。

【问题讨论】:

    标签: java generics arraylist bounded-wildcard


    【解决方案1】:

    你为什么不写:

    public List<IEvent> getEventsByDateRange(DateTime minStartTime, DateTime minEndTime)
    {
        List<IEvent> returnedEvents = new ArrayList<IEvent>();
        returnedEvents.add(new GoogleEvent());
        return returnedEvents;
    }
    

    【讨论】:

    • ArrayList&lt;GoogleEvent&gt;List&lt;IEvent&gt; 的分配不兼容。
    • 您不能将 ArrayList 分配给 List
    • 你不能这样做..它不是同一个对象类型
    • 抱歉忘记替换泛型参数
    • 现在你有一个问题,因为你不能创建一个 IEvents 的实例,它是一个接口
    【解决方案2】:

    这是不允许的。 returnedEvents 包含GoogleEvent 对象的列表,不得允许接受不是GoogleEvent 对象的对象。

    虽然在您的示例中您恰好传递了一个GoogleEvent,但您通过调用一个接受任何实现IEventadd 版本来实现这一点。根本不允许调用 add 方法,因为它可能导致列表存储 GoogleEvent 以外的内容。

    Java 通配符“编辑掉”会以这种方式破坏规则的方法。

    如果您需要返回该通配符列表类型,ArrayList&lt;GoogleEvent&gt; 就可以满足。

    注意这是一个完整的源文件,编译无误:

    import java.util.*;
    
    interface IEvent { }
    
    class GoogleEvent implements IEvent { }
    
    public class Foo {
        public ArrayList<? extends IEvent> getEventsByDateRange()  {
            ArrayList<GoogleEvent> returnedEvents = new ArrayList<GoogleEvent>();
            returnedEvents.add(new GoogleEvent());
            return (returnedEvents);
        }
    }
    

    【讨论】:

    • 我应该如何将 googleEvents 类的对象添加到实现 IEvents 的对象数组列表中?
    • 在返回语句中再次出现类型不匹配:无法从 List 转换为 ArrayList
    • ListArrayList?它们不一样。
    • @Mortalus - 查看更多更新,一个完整的源文件,您可以尝试编译。
    • 谢谢!!!!完美地工作..所以现在我应该能够使用 IEvent 接口访问所有糟糕的 GoogleEvents 了吗?
    【解决方案3】:

    您不需要使用? extends IEvent,因为仅使用IEvent,Java 将动态绑定GoogleEvent 类。这是多态性。

    【讨论】:

      【解决方案4】:

      解决办法:

      ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>();
      

      你的错误的原因是因为编译器试图做capture conversion

      在您的情况下,returnedEvents 捕获了一些扩展IEvent未知(即扩展/实现IEvent 的任何内容),并且您将其分配给参数化类型GoogleEvent)。

      编译器看到,returnedEvents.add(? extends IEvent) 没有使用 returnedEvents.add(GoogleEvent) 的签名进行验证,因为捕获占位符设置在 returnedEvents 上。

      【讨论】:

      • 这不会编译。不能在泛型实例化中使用通配符。
      • @John B,谢谢,我看到了,页面需要很长时间才能更新。我已经更新了我的帖子。
      【解决方案5】:
      public ArrayList<IEvent> getEventsByDateRange(DateTime minStartTime,
              DateTime minEndTime)
      {
          ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>();
          returnedEvents.add(new GoogleEvent());
          return (returnedEvents);
      }
      

      【讨论】:

        【解决方案6】:

        您不能写入使用? extends ... 声明的变量。只有使用? super ...时才允许写入。

        这可以用下面的例子来解释:

        List<GoogleEvent> googleEvents = new ArrayList<GoogleEvent>();
        ArrayList<? extends IEvent> returnedEvents = googleEvents;
        
        // Would be OK
        returnedEvents.add(new GooleEvent());
        
        // Would be OK to the definition of returnedEvents, 
        // but breaks the googleEvents.
        returnedEvents.add(new OtherEvent());
        

        您的简短解决方案是将returnedEvents 声明为List&lt;GoogleEvent&gt;

        【讨论】:

        • 返回类型不匹配:无法从 List 转换为 ArrayList
        • 使用列表 作为结果类型。一般哪个更好,因为您可以将 ArrayList 更改为另一个列表,例如。 g.、LinkedList不改变操作界面。
        • 添加演员ArrayList&lt;? extends IEvent&gt; returnedEvents = (ArrayList&lt;? extends IEvent&gt;)googleEvents;
        猜你喜欢
        • 2017-10-08
        • 2018-05-16
        • 2013-01-27
        • 1970-01-01
        • 2015-10-14
        • 1970-01-01
        • 2012-12-19
        • 2011-12-27
        • 2015-04-29
        相关资源
        最近更新 更多