2015-06-19 21 views
6

Ho una funzione statica con la seguente firma per un tipo generico Tpresunzione di un tipo generico da un tipo generico in Java (compilazione errore di tempo)

public static<T> List<T> sortMap(Map<T, Comparable> map) 

che dovrebbe restituire un elenco di chiavi mappa con alcune proprietà .

Ora voglio passare un HashMap generica di tipo S

Map<S,Double> map 

nel chiamare la funzione statica all'interno di una classe generica, che ha la mappa come una variabile membro.

Ho elencato un esempio di codice minimo di seguito.

Tuttavia, ricevo un messaggio di errore (S e T sono entrambi T ma in ambiti diversi del mio codice, vale a dire T#1 = T, T#2 = S):

required: Map<T#1,Comparable> 
    found: Map<T#2,Double> 
    reason: cannot infer type-variable(s) T#1 
    (argument mismatch; Map<T#2,Double> cannot be converted to Map<T#1,Comparable>) 

Come si può risolvere questo problema? Sono sorpreso che Java non consenta di inferire un tipo generico da un tipo generico. Quale struttura in Java si può usare per lavorare con quel tipo di ragionamento più astratto del codice?

Codice:

public class ExampleClass<T> { 
    Map<T, Double> map; 
    public ExampleClass() { 
     this.map = new HashMap(); 
    } 
    //the following line produces the mentioned error 
    List<T> sortedMapKeys = UtilityMethods.sortMap(map); 
} 

public class UtilityMethods { 
    public static<T> List<T> sortMap(Map<T, Comparable> map) { 
     // sort the map in some way and return the list 
    } 
} 
+0

Si prega di mostrare il codice della classe il pubblico. I metodi –

+0

'' static'' non possono accedere alle variabili membro; e quale versione di java usi? –

+0

Penso che dovrai aggiungere altro codice per capire il problema. –

risposta

7

Non è il problema con la T e S, ma con la Comparable e Double.

Il motivo dell'errore è un Map<T, Double> is not a Map<T, Comparable>.

Dovrai allargare un po 'l'ambito del secondo parametro di tipo. Qualcosa di simile:

public static <T, S extends Comparable<S>> List<T> function(Map<T, S> map) { 
    //implementation 
} 

Poi, sarete in grado di richiamare il metodo con:

Map<S, Double> map = new HashMap<S, Double>(); 
function(map); 
+0

questo si chiama [varianza] (https://msdn.microsoft.com/en-US/library/ee207183.aspx) –

+0

Grazie! Sono stato fuorviato dal messaggio del compilatore incentrato sui tipi generici. Inoltre, pensavo che il compilatore avrebbe capito che 'Double' è' Comparable' e che le interfacce sarebbero state gestite diversamente dall'ereditarietà delle classi per i generici. Continuo a pensare che la logica Java dell'uso della parola chiave 'extends' in generici per descrivere che mi aspetto un tipo 'S'that * implementa * e l'interfaccia sia un po' scadente. Mi manca qualcosa qui? Ha senso estendere e interfacciare * con i generici? – madison54

+0

Sì, 'extends' in Generics viene utilizzato per entrambe le classi e le interfacce. –

Problemi correlati