2015-04-11 4 views
1

Вот мой метод. Я хочу вернуть набор строк из Java-метода. Я хотел бы, чтобы вызывающий код решил, хочет ли он реализовать эту коллекцию как Vector или LinkedList или ArrayList или что-то еще, что реализует интерфейс List.Как вернуть интерфейс из метода

public List<String> findAvailableLanguages() { 
    Iterator<Map.Entry<String, String>> it = this.iterator(); 
    List<String> list = new ArrayList<String>(); 
    while (it.hasNext()) { 
     Map.Entry<String, String> n = it.next(); 
     list.add(n.getKey()); 
    } 

...

Однако, я должен создать экземпляр конкретного объекта класса внутри метода для того, чтобы построить коллекцию. Что я теперь верну, что будет совместимо с любым классом, который реализует List?

Возможно ли это?

+0

Вы знакомы с ['generics'] (https://docs.oracle.com/javase/tutorial/java/generics/boundedTypeParams.html)? –

ответ

4

Это более эффективно для абонентов, если вы позволите List быть переданы в процессе заполнения вместо инициировать свою собственную. Это также сделает код, который легко тестируется с помощью блока, так как это делает шаблон, известный как Injection Dependency.

public List<String> populateWithAvailableLanguages(List<String> list) { 
    Iterator<Map.Entry<String, String>> it = this.iterator(); 
    // List<String> list = new ArrayList<String>(); 
    while (it.hasNext()) { 
     Map.Entry<String, String> n = it.next(); 
     list.add(n.getKey()); 
    } 
} 

Теперь реализация List может быть определен абонентом:

List<String> availableLanguages = new ArrayList<>(); 
Localizer.populateWithAvailableLanguages(availableLanguages); 
+1

Я думаю, что лучше не возвращать список в этом случае (т. Е. Иметь тип возвращаемого типа), поскольку он создает путаницу.Также имя метода должно быть изменено на нечто вроде populateListWithAvailableLanguages, дающее понять, что список, переданный в аргументе, будет заполнен. – coder

+0

@coder: Отлично! Я на самом деле не сделал ничего, кроме копирования исходного кода и добавления битов, но ваши советы очень полезны для сохранения ремонтопригодности кода. – Unihedron

+0

Я использовал это решение и рассмотрел ответы на вопросы. Спасибо. – dacDave

-1

Ваш метод подписи должен быть ниже

Public Collection (? Супер List) findAvailableLanguages ​​() {}

1

Короче говоря, возвращающий объект типа ArrayList, который может быть брошена в любой другой тип объекта, который реализует список не представляется возможным , Элементы могут быть перемещены и добавлены к другому типу объекта, но сам тип коллекции не может быть отброшен.

Я объясню, почему. Когда вы говорите,

List<String> list = new ArrayList<String>(); 

ссылочный тип «список» - это список, а тип объекта - ArrayList. Объект «list», который вы теперь используете, дает вам доступ ко всем методам интерфейса List, но не к другим методам, которые ArrayList имеет, хотя объект списка может их видеть (вроде сужения преобразования). Вы можете отбросить этот объект списка обратно к объекту ArrayList, и это сработает, потому что экземпляр списка в любом случае может видеть методы, которые ArrayList имел и, следовательно, отбрасывает это назад, будет работать (вроде как расширение преобразования обратно к исходной ширине).

Но если вы должны были передать его одному из других классов, реализующих интерфейс List, например LinkedList или Vector или Stack, что произойдет? Экземпляр списка не знает, как реализуются другие методы, присутствующие в LinkedList, Vector или Stack (поскольку они не находятся в ArrayList). Так что это похоже на конверсию, в которой вы не знаете, что нужно сделать. Поэтому он отбросит ошибку компилятора.

Расширение этого, вы можете увидеть, если у вас:

List<String> list = new LinkedList<String>(); 

сейчас, бросая список обратно в LinkedList будет работать, но не обратно в ArrayList.

Смежные вопросы