2017-01-06 4 views
1

Для установки, у меня есть:Generic параметр возвращает List <ChildInterface> в потоке, но прямой метод возвращает список вызовов <Parent>

interface Parent 

interface Child1 extends Parent 

interface Child2 extends Parent 

И в другом месте у меня есть:

public class MyClass { 
    private List<Child1> child1List = new ArrayList<>(); 

    public List<Parent> getChild1List(Contact contact) { 
     return child1List.parallelStream() 
         .filter(m -> m.getContacts().contains(contact)) 
         .sorted(Comparator.comparing(Parent::getParentField)) 
         .collect(Collectors.toList()); 
    } 
} 

Когда я это делаю это way, getChild1List возвращает List<Parent> (не должен ли он возвращаться List<Child1>?)

Позже, я обнаружил, что поток полезен для других методов, поэтому я ext и он создал общий метод. У меня есть несколько интерфейсов, которые расширяют Parent, так что я следующим образом:

private <T extends Parent> List<T> returnsListByContact(List<T> childList, Contact contact) { 
     return childList.parallelStream() 
         .filter(m -> m.getContacts().contains(contact)) 
         .sorted(Comparator.comparing(Parent::getParentField)) 
         .collect(Collectors.toList()); 
    } 

и getChild1List(Contact contact) стали:

public List<Parent> getChild1List(Contact contact) { 
     return returnsListByContact(child1List, contact); 
    } 

, но теперь это не нравится, ссылаясь, что getChild1List возвращается в List<Child1>. Я не понимаю, почему, поскольку реализация потока не была изменена вообще, за исключением того, что дочерний список, который запускает его, прошел через общий параметр, а не прямой вызов в поле частного члена MyClass.

Так почему же они возвращают две разные вещи?

+1

Я исправил форматирование. Используйте обратные кавычки для кода, который является встроенным, и отступ на четыре пробела для форматирования блока кода. Если вы хотите, чтобы код показывал отступ в четыре пробела, вам нужно добавить четыре пробела, чтобы отформатировать его как блок кода, а затем добавить * дополнительные * четыре пробела для видимости отступа. Не используйте вкладки. –

+0

Спасибо! Я не мог понять, как заставить блоки оставаться твердыми при написании нескольких строк. – NateH06

ответ

5

(пример путает ли Meeting действительно Parent.?)

В первой версии getChild1List, метод collect(toList()) называется на Stream<Child1> и целевой тип - определяется типом возвращаемого getChild1List - есть List<Parent>. Это работает, потому что разрешено собирать поток типа T сборщиком супертипа T. В частности, вы добавляете экземпляры типа Child1 в List<Parent>, который является безопасным по типу и разрешен. Вы могли бы также изменить объявление getChild1List(), чтобы вернуть List<Child1> вместо List<Parent>.

Вы можете увидеть, где дисперсия разрешено смотреть на объявления collect() в Stream<T>:

<R,A> R collect(Collector<? super T,A,R> collector) 

? super T что позволяет дисперсию.

Ваше заявление о returnsListByContact,

<T extends Parent> List<T> returnsListByContact(List<T> childList, ...) 

делает не позволяют дисперсии. Он принимает параметр типа List<T> и возвращает List<T>. Параметр и тип возврата должны быть идентичными. Вот почему есть несоответствие, когда вы проходите в List<Child1> и пытаетесь вернуть его из метода, тип возврата которого List<Parent> - эти типы несовместимы.

Чтобы исправить это, вам нужно добавить некоторое отклонение от вашего объявления returnsListByContact.Вот как я это сделать:

<T extends Parent> List<T> returnsListByContact(List<? extends T> childList, ...) 

Это позволяет возвращать список некоторого типа при переходе в список некоторого подтипа, в этом случае возвращение List<Parent> при прохождении в List<Child1>, что то, что я думаю, что вы хотеть.

+2

плюс один для первого предложения, я тоже не мог обойти его. – Eugene

+0

Да, собрание - это настоящее имя - все его экземпляры были Родительскими. Отредактировал мой исходный код, чтобы быть более четким. Думал, что я очистил свой код, иронически сделать это понятным для всего населения ... слишком много часов в этом проекте .... – NateH06

+0

Пришло время обработать это и ваше исправление работало чудесно. Я думал, что тип возвращаемого типа .collect() 'был основан на том, что вы подавали в« Stream », и не знал, что возвращаемый тип метода имел какое-либо отношение к результату. Спасибо огромное! – NateH06