2015-05-12 17 views
5

Ho ArrayList<Unit> units. Voglio scrivere una funzione che restituisca tutti gli oggetti della sottoclasse specificata, che viene usata come parametro. Tuttavia non riesco a farlo funzionare. Ecco quello che ho:estraendo tutte le istanze di sottoclasse dall'arrayist

public static ArrayList<? extends Unit> getTheseUnits(Class<? extends Unit> specific_unit) { 
    ArrayList<specific_unit> res = new ArrayList<>(); //'specific_unit' is in red here. Adding '.class' or '.getClass()' after it does not resolve anything 
    for (Unit u : units){ 
     if (u instanceof specific_unit){ 
      res.add(u); 
     } 
    } 
    return res; 
} 
+0

"È rosso qui dentro" si traduce in un errore del compilatore. Forse dovresti davvero imparare alcune nozioni di base di Java prima di provare a lavorare su tale codice. Significato: scopri concetti elementari come errori del compilatore (e come leggerli), prima di passare a un uso sofisticato di tipi generici! Il tuo "rosso qui dentro" si riduce a: non puoi usare un nome di variabile come tipo generico, quindi 'ArrayList ' non è una dichiarazione Java corretta. – GhostCat

+0

@ Jägermeister Capisco che si tratta di un errore del compilatore, tuttavia Eclipse non aiuta molto affermando che 'specifica_unità non può essere risolta' –

risposta

4

filtrarli per classe:

public static List<Unit> getUnitsByClass(Class<? extends Unit> specificClass, List<? extends Unit> units) { 
    return units.stream() 
       .filter(e -> e.getClass().equals(specificClass)) 
       .collect(Collectors.toList()); 
} 

Se si vuole fare questo metodo parametrizzata, per usare un'altra opzione:

public static <T extends Unit> List<T> getUnitsByClass(Class<T> specificClass, List<? extends Unit> units) { 
    return (List<T>) units.stream() 
          .filter(e -> e.getClass().equals(specificClass)) 
          .collect(Collectors.toList()); 
} 

ma nel secondo approccio, riceverai un avviso di cast non controllato.

+0

Penso che la tua risposta sia un po 'corta. Sembra che non abbia alcuna comprensione dei tipi generici; quindi potrebbe non essere in grado di capire che il tuo "SpecificUnit.class" è qualcosa di diverso dalla sua variabile "specifica_unità". – GhostCat

+0

La variabile 'specific_unit' di OP di Jägermeister è di tipo classe, l'ho rinominata in' specificClass' per renderla più chiara. –

+0

@ Jägermeister forse non capisco come ottenere i farmaci generici tutto il tempo, ma non sono stupido. –

4

Non è possibile utilizzare instanceof sulla variabile. Invece, dovresti usare isInstance.

Basta sostituire questa linea:

if (u instanceof specific_unit) { 

con

if (specific_unit.isInstance(u)){ 
+0

Solo per completezza: il suo metodo non verrà ancora compilato, poiché usa anche specific_unit come parametro tipo durante la creazione l'arraylist del "valore di ritorno". Potresti voler aggiornare la tua risposta anche su questo aspetto. – GhostCat

2

Se si modifica la firma del metodo può funzionare:

public static <T extends Unit> ArrayList<T> getTheseUnits(Class<T> specific_unit) { 
    ArrayList<T> res = new ArrayList<>(); 
    for (Unit u : units){ 
     if (specific_unit.isAssignableFrom(u.getClass()) { 
      res.add(u); 
     } 
    } 
    return res; 
} 

è sufficiente utilizzare un tipo specifico per la generica (<T>) invece di un carattere jolly (?). Questo è necessario per creare il tipo di reso (ArrayList<T>).

Inoltre, è necessario utilizzare isAssignableFrom() anziché instanceof. Si prega di notare che isAssignableFrom() controlla anche i sottotipi.

Controllare di nuovo questo codice poiché non è stato testato.

+0

Perché utilizzare "T" quando il tipo è irrilevante; e quindi "?" farebbe? – GhostCat

+0

@ Jägermeister il tipo 'T' è necessario per definire un nuovo' ArrayList' (l'errore del compilatore nella domanda). –

1

provare questo:

public static <T extends Unit> ArrayList<T> getTheseUnits(Class<T> specific_unit) { 
    ArrayList<T> res = new ArrayList<T>(); 
    for (Unit u : units){ 
     if (specific_unit.isInstance(u)){ 
      res.add((T) u); 
     } 
    } 
    return res; 
} 
0

forse si può cercare di non utilizzare le classi, ma le interfacce in dichiarazione e ritorno (in modo Lista invece di ArrayList e Unità invece di SpecificUnit). Ho rinominato le classi e le istanze nello stile java ... Quindi ad esempio:

public static List<? extends Unit> getTheseUnits(Class<? extends Unit> specificUnit, List<Unit> units) { 
    List<Unit> res = new ArrayList<Unit>(); 
    for (Unit u : units){ 
     if (specificUnit.isInstance(u)){ 
      res.add(u); 
     } 
    } 
    return res; 
} 

compila. Probabilmente è quello che stai cercando ... fammi sapere se è utile

Problemi correlati