Java Generics, differenza tra due metodi firme con parametro jolly vs tipo

2

Ho difficoltà a cercare di capire perché le due dichiarazioni di metodi hanno risultati diversi.

Sulla prima firma del metodo è ovvio che non puoi confrontare mele con mele e arance con Orange, perché nessuno di loro implementa Paragonabile < >.

Ma sul secondo metodo sono rimasto sorpreso dal fatto che potresti effettivamente confrontare le mele con mele e arance con le arance.

Ricordo che su una versione precedente di IntelliJ (14) una chiamata al secondo metodo con un elenco di mele o arance stava dando un errore di compilazione. Ma le versioni più recenti di IntelliJ non segnalano più questo problema.

Sarei grato se qualcuno potesse spiegarmi qual è la differenza tra i due metodi di firma usando l'esempio di Fruit.

class Fruit implements Comparable<Fruit> {}

class Apple extends Fruit {
}

class Orange extends Fruit {
}

static <T extends Comparable<T>> T maxSimple(Collection<T> coll) {
}

static <T extends Comparable<T>> T max(Collection<? extends T> coll) {
}
    
posta HugoMelo 18.10.2016 - 10:37
fonte

2 risposte

4

Quali sono i vincoli su T?

Nel tuo primo esempio, T deve essere uguale al tipo di raccolta ed essere paragonabile esattamente a se stesso. Tieni presente che List<Apple> non estende List<Fruit> e, in caso affermativo, potresti aggiungere Oranges all'elenco delle mele.

Prova T come Apple : Apple non è Comparable<Apple> , quindi questo fallisce. Prova T come Fruit : Collection<Fruit> non è un supertipo di Collection<Apple> , quindi fallisce

Nel secondo esempio, consenti al tipo di raccolta di superare i sottotipi di T , quindi T può essere Fruit e hai Collection< any fruit subtype >

C'è una terza opzione che non hai considerato:

static <T extends Comparable<? super T> T max(Collection<T> coll) 

Qui permettiamo a T di essere legato ad Apple, in quanto Apple è paragonabile a una delle sue superclassi

    
risposta data 18.10.2016 - 10:59
fonte
2

List<Apple> è una raccolta di un certo tipo ( Apple ) che deriva da un certo tipo T che implementa Comparable<T> (Fruit). Quindi il secondo metodo corrisponde alla situazione data. D'altra parte, Apple non implementa Comparable<Apple> in modo che il primo metodo non sia applicabile.

E sì, puoi confrontare le mele con le mele, le arance con le arance, le mele con le arance e le arance con le mele, perché tutte sono frutta e frutta sono paragonabili ad altre frutta.

    
risposta data 18.10.2016 - 10:59
fonte

Leggi altre domande sui tag