Общий: ArrayList из?Расширяет ISomeInterface в Java - PullRequest
3 голосов
/ 19 октября 2011

У меня возникли некоторые проблемы в следующем коде.

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

Это возвращает следующую ошибку компиляции для "returnEvents.add (new GoogleEvent ()); строка кода":

Метод add (capture # 1-of-extends IEvent) в типе ArrayList не применим для аргументов (GoogleEvent)

Объявление класса GoogleEventследующим образом:

public class GoogleEvent implements IEvent {...}

Я знаю, что есть некоторые хитрые части, использующие дженерики в Java, таким образом, подстановочные знаки, но я не могу понять это.

Спасибо.

Ответы [ 6 ]

5 голосов
/ 19 октября 2011

Почему бы вам не написать:

public List<IEvent> getEventsByDateRange(DateTime minStartTime, DateTime minEndTime)
{
    List<IEvent> returnedEvents = new ArrayList<IEvent>();
    returnedEvents.add(new GoogleEvent());
    return returnedEvents;
}
2 голосов
/ 19 октября 2011

Решение:

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

Причина вашей ошибки в том, что компилятор пытается преобразовать захват .

В вашем случае returnedEvents захватываетнекоторый неизвестный , который расширяет IEvent (то есть все, что расширяет / реализует IEvent), и вы присваиваете его параметризованному типу GoogleEvent).

Компилятор видит, returnedEvents.add(? extends IEvent), который не проверяется с подписью returnedEvents.add(GoogleEvent), поскольку заполнитель захвата установлен на returnedEvents.

2 голосов
/ 19 октября 2011

Вам не нужно использовать ? extends IEvent, поскольку при использовании только IEvent Java будет динамически связывать класс GoogleEvent.Это полиморфизм.

2 голосов
/ 19 октября 2011

Это не разрешено.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);
    }
}
0 голосов
/ 19 октября 2011

Вы не можете записать в переменную, которая объявлена ​​с ? 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());

Краткое решение для вас - объявить returnEvents как List<GoogleEvent>.

0 голосов
/ 19 октября 2011
public ArrayList<IEvent> getEventsByDateRange(DateTime minStartTime,
        DateTime minEndTime)
{
    ArrayList<IEvent> returnedEvents = new ArrayList<IEvent>();
    returnedEvents.add(new GoogleEvent());
    return (returnedEvents);
}
...