2009-03-19 2 views
26

Пожалуйста, обратите внимание на следующий фрагмент кода:Как я могу нарисовать список с помощью дженериков в Java?

public interface MyInterface { 

    public int getId(); 
} 

public class MyPojo implements MyInterface { 

    private int id; 

    public MyPojo(int id) { 
     this.id = id; 
    } 

    public int getId() { 
     return id; 
    } 

} 

public ArrayList<MyInterface> getMyInterfaces() { 

    ArrayList<MyPojo> myPojos = new ArrayList<MyPojo>(0); 
    myPojos.add(new MyPojo(0)); 
    myPojos.add(new MyPojo(1)); 

    return (ArrayList<MyInterface>) myPojos; 
} 

Ответный заявление делает кастинг, который не компилируется. Как преобразовать список myPojos в более общий список, , без необходимости проходить через каждый элемент списка?

Благодаря

ответ

41

Измените метод использовать подстановочные:

public ArrayList<? extends MyInterface> getMyInterfaces() {  
    ArrayList<MyPojo> myPojos = new ArrayList<MyPojo>(0); 
    myPojos.add(new MyPojo(0)); 
    myPojos.add(new MyPojo(1)); 

    return myPojos; 
} 

Это предотвратит вызывающему от попыток добавить другие реализации интерфейса к списку. В качестве альтернативы, вы можете просто написать:

public ArrayList<MyInterface> getMyInterfaces() { 
    // Note the change here 
    ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0); 
    myPojos.add(new MyPojo(0)); 
    myPojos.add(new MyPojo(1)); 

    return myPojos; 
} 

Как обсуждалось в комментариях:

  • Возвращение безразличных коллекции может быть неудобно для абонентов
  • Это, как правило, лучше использовать интерфейсы вместо конкретных типов для возвращения типы. Таким образом, предлагаемая подпись, вероятно, будет один из:

    public List<MyInterface> getMyInterfaces() 
    public Collection<MyInterface> getMyInterfaces() 
    public Iterable<MyInterface> getMyInterfaces() 
    
+0

2-е решение лучше одного ИМХО. Возвращение диких карт обычно считается плохой практикой, b/c ограничивает клиентский код. В этом случае с ArrayList вы могли только читать из списка и не могли ничего добавить к нему. –

+0

Это может быть то, что нужно, конечно - мы просто не знаем. (Это почти наверняка использовать список вместо ArrayList , а также, или, возможно, просто Iterable или Коллекция .) –

+1

+1 для использования более общего типа (например список , коллекция ). Но возвращаемые подстановочные знаки редко бывают то, что вы хотите. Если вы склоняетесь к неизменности, есть лучшие способы сделать это. Нафталин и Вадлер рассказывают об этом в «Java Generics and Collections». –

4

Вы должны делать:

public ArrayList<MyInterface> getMyInterfaces() { 
    ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0);  
    myPojos.add(new MyPojo(0));  
    myPojos.add(new MyPojo(1));  
    return myPojos; 
} 
0

В этом случае, я хотел бы сделать это следующим образом:

public ArrayList<MyInterface> getMyInterfaces() { 

    ArrayList<MyInterface> myPojos = new ArrayList<MyInterface>(0); 
    myPojos.add(new MyPojo(0)); 
    myPojos.add(new MyPojo(1)); 

    return myPojos; 
} 

MyPojo ist типа MyInterface (поскольку он реализует интерфейс). Это означает, что вы можете просто создать список с необходимым интерфейсом.

0

Попробуйте использовать интерфейсы везде, за исключением при создании экземпляров, и вы проблемы исчезнут:

public List<MyInterface> getMyInterfaces() 
{ 
    List<MyInterface> myInterfaces = new ArrayList<MyInterface>(0); 
    myInterfaces.add(new MyPojo(0)); 
    myInterfaces.add(new MyPojo(1)); 

    return myInterfaces; 
} 

Как и другие уже говорил, использование MyInterface исправляет проблему. Также лучше использовать интерфейс List вместо ArrayList для возвращаемых типов и переменных.

+0

Использование списка - это не то, что его исправляет, но использование MyInterface вместо MyPojo в качестве аргумента типа. –

+0

Да, это вводит в заблуждение, исправлено это сейчас. – starblue

24

Выбор правильного типа с самого начала - лучше всего, однако, чтобы ответить на ваш вопрос, вы можете использовать стирание типа.

return (ArrayList<MyInterface>) (ArrayList) myPojos;

+3

IMO, это должен быть ответ, поскольку в некоторых случаях вы просто не можете добавлять элементы в коллекцию базового типа: подумайте о наборе результатов JPA из запросов, вы получили список объектов JPA, и если вам нравится верните этот список вызывающему, используя некоторый абстрагирующий интерфейс над сущностью (постоянство агностик), совет Петра * * путь –