Generic:ArrayList of?在Java中扩展ISomeInterface

时间:2011-10-19 12:09:45

标签: java generics arraylist bounded-wildcard

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

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());代码行”返回以下编译错误:

  

该方法在类型中添加(捕获#1-of?extends IEvent)   ArrayList不适用于   参数(GoogleEvent)

班级GoogleEvent的声明如下:

public class GoogleEvent implements IEvent {...}

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

感谢。

6 个答案:

答案 0 :(得分:5)

你为什么不写:

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

答案 1 :(得分:2)

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

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

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

如果您需要返回该通配符列表类型,ArrayList<GoogleEvent>可以满足要求。

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

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);
    }
}

答案 2 :(得分:2)

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

答案 3 :(得分:2)

解决方案:

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

出错的原因是编译器正在尝试执行capture conversion

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

您无法编写使用? 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<GoogleEvent>