3

我在下面的代码中遇到了一些麻烦。

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”返回以下编译错误:

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

类的声明GoogleEvent如下:

public class GoogleEvent implements IEvent {...}

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

谢谢。

4

6 回答 6

5

你为什么不写:

public List<IEvent> getEventsByDateRange(DateTime minStartTime, DateTime minEndTime)
{
    List<IEvent> returnedEvents = new ArrayList<IEvent>();
    returnedEvents.add(new GoogleEvent());
    return returnedEvents;
}
于 2011-10-19T12:13:39.443 回答
2

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

尽管在您的示例中您碰巧传递了 a GoogleEvent,但您是通过调用一个add接受任何实现的版本来做到这一点的IEventadd根本不允许调用该方法,因为它可能导致列表存储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);
    }
}
于 2011-10-19T12:14:24.030 回答
2

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

于 2011-10-19T12:14:34.907 回答
2

解决方案:

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

您的错误的原因是因为编译器正在尝试进行捕获转换

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

编译器看到,当捕获占位符设置为 on 时,returnedEvents.add(? extends IEvent)它不会使用签名验证。returnedEvents.add(GoogleEvent)returnedEvents

于 2011-10-19T12:15:25.620 回答
0
public ArrayList<IEvent> getEventsByDateRange(DateTime minStartTime,
        DateTime minEndTime)
{
    ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>();
    returnedEvents.add(new GoogleEvent());
    return (returnedEvents);
}
于 2011-10-19T12:17:21.797 回答
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>.

于 2011-10-19T12:20:10.490 回答