Sto leggendo dei metodi generici da OracleDocGenericMethod . Sono piuttosto confuso riguardo al confronto quando dice quando usare i caratteri jolly e quando usare metodi generici. Citando dal documento.
interface Collection<E> { public boolean containsAll(Collection<?> c); public boolean addAll(Collection<? extends E> c); }
Avremmo potuto utilizzare metodi generici qui invece:
interface Collection<E> { public <T> boolean containsAll(Collection<T> c); public <T extends E> boolean addAll(Collection<T> c); // Hey, type variables can have bounds too! }
[…] Questo ci dice che l'argomento type è utilizzato per il polimorfismo; il suo unico effetto è quello di consentire l'utilizzo di una varietà di tipi di argomenti effettivi in diversi siti di invocazione. In tal caso, è necessario utilizzare i caratteri jolly. I caratteri jolly sono progettati per supportare la sottotipizzazione flessibile, che è ciò che stiamo cercando di esprimere qui.
Non pensiamo che anche il carattere jolly (Collection<? extends E> c);
supporti il polimorfismo? Allora perché l'uso del metodo generico è considerato non buono in questo?
Proseguendo, afferma,
I metodi generici consentono di utilizzare parametri di tipo per esprimere le dipendenze tra i tipi di uno o più argomenti da un metodo e / o dal suo tipo restituito. Se non esiste una tale dipendenza, non dovrebbe essere utilizzato un metodo generico.
Cosa significa questo?
Hanno presentato l'esempio
class Collections { public static <T> void copy(List<T> dest, List<? extends T> src) { ... }
[...]
Avremmo potuto scrivere la firma per questo metodo in un altro modo, senza utilizzare i caratteri jolly:
class Collections { public static <T, S extends T> void copy(List<T> dest, List<S> src) { ... }
Il documento scoraggia la seconda dichiarazione e promuove l'uso della prima sintassi? Qual è la differenza tra la prima e la seconda dichiarazione? Entrambi sembrano fare la stessa cosa?
Qualcuno può illuminare quest'area.
?
. Potresti riscriverlo come `public static <T1 extends Number, T2 extends Number> void copy (List <T1> dest, List <T2> src) e in questo caso diventa ovvio cosa sta succedendo.