2009-03-19 16 views
26

Proszę rozważyć następujący fragment:Jak mogę rzucić listę używając generycznych w Javie?

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; 
} 

Instrukcja return robi casting że nie kompiluje. Jak mogę przekonwertować listę myPojos na bardziej ogólną listę, , bez konieczności przechodzenia przez każdą pozycję z listy?

Dzięki

Odpowiedz

41

zmienić metodę użyć symbolu wieloznacznego:

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

    return myPojos; 
} 

To zapobiegnie rozmówcę z próby dodania inne implementacje interfejsu do listy. Alternatywnie, można po prostu napisać:

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; 
} 

Jak wspomniano w komentarzach:

  • Powracające zbiory symbolami wieloznacznymi mogą być niewygodne dla dzwoniących
  • Zazwyczaj lepiej używać interfejsów zamiast konkretnych typów powrotu typy. Więc sugeruje podpis będzie prawdopodobnie jednym z:

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

Drugie rozwiązanie to lepsze jedno IMHO. Zwracanie dzikich kart jest ogólnie uważane za złą praktykę, b/c ogranicza kod klienta. W tym przypadku z ArrayList mogłeś tylko czytać z listy i nie mógł nic dodać. –

+0

Oczywiście może być to, o co nam chodzi - po prostu nie wiemy. (Należy używać prawie na pewno Lista zamiast ArrayList , jak również, a może po prostu iterowalny lub Collection .) –

+1

+1 za korzystanie rodzaje bardziej ogólnych (np Lista , kolekcja ). Ale powracających symboli wieloznacznych rzadko jest to, co chcesz. Jeśli jesteś skłonny do niezmienności, istnieją lepsze sposoby robienia tego. Naftalin & Wadler opowiadają o tym w "Java Generics and Collections". –

4

należy robić:

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

W tym przypadku, chciałbym zrobić to tak:

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 typu MyInterface (ponieważ implementuje interfejs). Oznacza to, że możesz po prostu utworzyć listę z interfejsem, którego potrzebujesz.

0

spróbuje użyć interfejsów wszędzie z wyjątkiem przy konstruowaniu instancji, a problemy znikną:

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

    return myInterfaces; 
} 

Jak inni już wspomniano, stosowanie MyInterface rozwiązuje problemu. Lepiej jest także użyć interfejsu List zamiast ArrayList dla typów i zmiennych zwracanych.

+0

Użycie Listy nie jest tym, co ją naprawia - jest to użycie MyInterface zamiast MyPojo jako argumentu typu. –

+0

Tak, to było mylące, naprawiono to teraz. – starblue

24

Wybór odpowiedniego typu od samego początku jest najlepszy, jednak aby odpowiedzieć na pytanie, można użyć funkcji usuwania typu.

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

+3

IMO, to powinna być odpowiedź, ponieważ w niektórych przypadkach po prostu nie możesz dodać pozycji do kolekcji typu podstawowego: pomyśl o zestawie wyników JPA z zapytań, masz listę podmiotów WZP i jeśli chcesz zwróć tę listę do osoby dzwoniącej za pomocą jakiegoś interfejsu abstrakcyjnego nad jednostką (agnostyka trwałości), rada Piotra jest * droga * –

Powiązane problemy