2013-03-12 24 views
19

Ho lezioni in programmazione avanzata presso la mia università e ho qualche problema a capire come funziona questo codice.Polimorfismo avanzato in Java

public final class GenericClass<T> { 
    private void overloadedMethod(Collection<?> o) { 
     System.out.println("Collection<?>"); 
    } 

    private void overloadedMethod(List<Number> o) { 
     System.out.println("List<Number>"); 
    } 

    private void overloadedMethod(ArrayList<Integer> o) { 
     System.out.println("ArrayList<Integer>"); 
    } 

    public void method(List<T> l) { 
     overloadedMethod(l); 
    } 

    public static void main(String[] args) { 
     GenericClass<Integer> test = new GenericClass<Integer>(); 
     test.method(new ArrayList<Integer>()); 
    } 
} 

Perché questo codice stampa "Collection <? >"?

risposta

14

La dichiarazione di method(List<T> l) non specifica alcun limite sul tipo T. Non vi è alcuna garanzia che T sia Numero o una sottoclasse di Numero. Pertanto, il compilatore può solo decidere che questo metodo chiama overloadedMethod(Collection<?> o).

Ricorda: dopo la compilazione, le informazioni sui generici non sono più disponibili nei file di classe.

+0

grazie, la vostra risposta spiega anche il motivo per cui dopo aver cambiato 'overloadedMethod (Lista o)' a 'overloadedMethod (Lista o)' programma stampa 'Lista ' invece di 'Collection ' –

+0

la la cosa più importante è la tua ultima frase. Questo spiega tutto! –

+0

Risposta abbastanza buona, ma -1 per attirare la vostra attenzione sul fatto che la dichiarazione di 'GenericClass ', invece, restituisce la stessa chiamata a 'overloadedMethod (Collection )'. Quindi c'è qualcos'altro che succede qui. –

-1

Ogni volta che si definisce un tipo generico, un corrispondente di tipo grezzo viene fornito automaticamente Questo metodo

public void method(List<T> l) { 

} 

sta sostituendo con

public void method(List<Object> l) { 

} 

Se leggete sui tipi di jolly, Vedrete che List<Number> e List<Object> o ArrayList<Integer> e List<Object> non ha alcun tipo di relazione. List<Object> è un sottotipo di Collecion<?> pertanto viene chiamato questo metodo.

+0

In realtà, il ragionamento qui non è sufficiente per rispondere alla domanda. Il compilatore decide quale overload di metodo chiamare, cosa che avviene * prima della cancellazione del tipo *. –

-1

quando avete a che fare con il metodo sovraccarico è necessario mettere tre concetti in mente:

  1. Ampliamento
  2. Boxing
  3. Var_args

il problema risiede nel primo punto che si sta ampliando , il compilatore java dà priorità a ciascuno di questi concetti nello stesso ordine in cui sono elencati sopra, quindi preferisce l'allargamento e quando chiami il tuo metodo come test.method(new ArrayList<Integer>()); il compilatore trova che ArrayList<Integer>() può essere ampliato a Collection<?> e poiché ha la priorità più alta chiama queste versioni e trascura le altre Nota: se si modifica la dichiarazione degli altri due metodi su private void overloadedMethod(ArrayList<?> o) e private void overloadedMethod(List<?> o) il compilatore chiamerà anche il Collection<?> versione perché è la preferita

+0

No. se privato sovraccaricatoMetodo (Lista o) {//, quindi il metodo Elenco verrà chiamato sulla raccolta . – AmitG

+0

l'hai provato ?? –

+0

"@Java Player: continuo a visitare questo forum anche in ufficio e mi tengo aggiornato il prima possibile BTW lo hai provato? Se ci provassi, per favore lascia perdere la conclusione qui – AmitG