2016-03-01 19 views

risposta

19

La firma proposta probabilmente funzionerebbe in Java-8. Tuttavia nelle precedenti versioni di Java l'inferenza di tipo non era così intelligente. Considera che hai List<java.sql.Date>. Notare che java.sql.Date estende java.util.Date che implementa Comparable<java.util.Date>. Quando si compila

List<java.sql.Date> list = new ArrayList<>(); 
Collections.sort(list); 

Funziona perfettamente in Java-7. Qui T è dedotto per essere java.sql.Date che è in realtà Comparable<java.util.Date> che è Comparable<? super java.sql.Date>. Tuttavia proviamo la tua firma:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {} 

List<java.sql.Date> list = new ArrayList<>(); 
sort(list); 

Qui T può essere presupposta come java.util.Date. Tuttavia, le specifiche Java 7 non consentono tale inferenza. Quindi questo codice può essere compilato con Java-8, ma non riesce quando compilato sotto Java-7:

Main.java:14: error: method sort in class Main cannot be applied to given types; 
     sort(list); 
     ^
    required: List<? extends T> 
    found: List<Date> 
    reason: inferred type does not conform to declared bound(s) 
    inferred: Date 
    bound(s): Comparable<Date> 
    where T is a type-variable: 
    T extends Comparable<T> declared in method <T>sort(List<? extends T>) 
1 error 

Tipo inferenza è notevolmente migliorata in Java-8. A JLS chapter 18 è dedicato separatamente, mentre in Java-7 le regole were sono molto più semplici.

+1

Ma come funziona statico > T max (Collection c) funziona bene ... si tratta ancora di un problema di inferenza? – prvn

+0

@prvn, qui hai 'Comparabile ' invece di 'Comparabile ' come nella tua firma proposta. '> void sort (Lista )' funzionerebbe anche, ma aggiungendo '? Estende T' è completamente inutile qui, mentre ragionevole nel metodo 'max' (come' max' restituisce il valore). –

+6

C'è un altro punto. Quando si ha un tipo jolly come 'Lista lista' non si può fare' list.set (index, list.get (anotherIndex)) 'all'interno del metodo, a causa del funzionamento dei tipi di caratteri jolly. Questo può essere aggirato con un metodo di supporto interno che cattura '? estende T' in un'altra variabile di tipo (o usando operazioni non controllate come spesso fanno le implementazioni interne), ma ancora, un tipo senza caratteri jolly è più pulito per un elenco che verrà modificato. – Holger

4

Differiscono perché ? super T è meno restrittivo di T. Si tratta di una Lower Bounded Wildcard (Java Tutorial legata dice, in parte)

Il termine List<Integer> è più restrittiva rispetto List<? super Integer> perché il primo corrisponde a un elenco di tipo Integer solo, mentre il secondo corrisponde a un elenco di qualsiasi tipo che è un supertipo di Integer.

Sostituire Integer con T e significa un To un java.lang.Object.

+0

ma sto aumentando la flessibilità nell'argomento di sort() ..usando? extends, – prvn

+0

Sì, nessuno ha detto che 'Elenco 'è lo stesso di' Lista '. La seconda versione usa 'extends' e la domanda è se questo lo rende uguale. – JojOatXGME

+0

Non penso che la tua risposta sia direttamente correlata alla domanda. – yuxh

9
// 0 
public static <T extends Comparable<? super T>> void sort0(List<T> list) 

// 1 
public static <T extends Comparable<T>> void sort1(List<? extends T> list) 

Queste firme differiscono in quanto impongono requisiti diversi sul rapporto tra tipo T e il tipo argomento per Comparable nella definizione di T.

Supponiamo per esempio di avere questa classe:

class A implements Comparable<Object> { ... } 

Quindi se avete

List<A> list = ... ; 
sort0(list); // works 
sort1(list); // fails 

La ragione sort1 non è che non c'è non tipo T che sia paragonabile a se stesso e cioè, o è un supertipo di, il tipo della lista.

Si scopre che la classe A non è valida, poiché gli oggetti che sono Comparable devono soddisfare determinati requisiti. In particolare, invertire il confronto dovrebbe invertire il segno del risultato. Possiamo confrontare un'istanza di A in un Object ma non viceversa, quindi questo requisito è violato. Tuttavia, si noti che questo è un requisito della semantica di Comparable e non è imposto dal sistema di tipi. Considerando solo il sistema di tipi, le due dichiarazioni sort sono davvero diverse.