2013-07-19 20 views
12

Si consideri il codice:tipo derivato non è un sostituto valido per un tipo generico Paragonabile

public abstract class Item<T> implements Comparable<T> 
{ 
    protected T item; 

    public int compareTo(T o) 
    { 
     return 0; // this doesn't matter for the time being 
    } 
} 

public class MyItem<T> extends Item<String> 
{ 
    T object; 
} 

public class Foo<T> 
{ 
    protected ArrayList<T> list; 
} 

public class Bar<V> extends Foo<MyItem<V>> 
{ 
    public void sort() 
    { 
     Collections.sort(list); 
    } 
} 


La chiamata sorta dà l'errore:

Bound mismatch: The generic method sort(List< T >) of type Collections is not applicable for the arguments (ArrayList< MyItem< T > >). The inferred type MyItem< T > is not a valid substitute for the bounded parameter < T extends Comparable< ? super T > >


Perché questo è sbagliato?

Se MyItem<V> implementa Comparable allora perché non è un sostituto?

Scusate se è stato chiesto, ma ritengo che la domanda sia in qualche modo specifica.

risposta

11

spiegazione realtà più dettagliata di questo errore dà il vostro javac stessa:

java: no suitable method found for sort(java.util.ArrayList<MyItem<V>>)

method java.util.Collections.<T>sort(java.util.List<T>,java.util.Comparator<? super T>) is not applicable (cannot instantiate from arguments because actual and formal argument lists differ in length)

method java.util.Collections.<T>sort(java.util.List<T>) is not applicable (inferred type does not conform to declared bound(s) inferred: MyItem<V> bound(s): java.lang.Comparable<? super MyItem<V>>)

Quindi, la domanda principale è:
perché è il metodo Collections.<T>sort(java.util.List<T>)) non sono applicabili?

La risposta è:
perché in Collections.<T>sort(java.util.List<T>) dichiarazione di metodo ci sono limiti sul parametro T: <T extends Comparable<? super T>>.

In altre parole, T deve implementare l'interfaccia Comparable su di esso. Ad esempio l'interfaccia di classe String implementa: ...implements ... Comparable<String>.

Nella classe caso Item non implementa tale interfaccia:

Item<T> implements Comparable<T> non è stessa cosa di Item<T> implements Comparable<Item<T>>.

Così, per risolvere questo problema, il tuo dovrebbe cambiare la classe Item a questo:

public abstract class Item<T> implements Comparable<Item<T>> 
{ 
    protected T item; 

    public int compareTo(Item<T> o) 
    { 
     return 0; // this doesn't matter for the time being 
    } 
} 
+1

Quella era perfetto. Saluti! Per chiarimenti, ho incluso le classi extra perché il codice che ho fornito è una versione molto più semplificata del mio codice reale, e non ero sicuro di dove fosse il problema. Ho completamente perso il fatto che potevo semplicemente cambiare il confronto vero e proprio. Grazie ancora. – terrorcell

+0

Migliore: 'classe astratta pubblica Articolo attrezzi comparabili > '- no? –

0

Non c'è bisogno di avere la classe MyItem generified solo per vedere l'effetto. La classe seguente è sufficiente per vedere cosa succede:

public class MyItem extends Item<String> {} 

Ora si ha la seguente chiamata:

Collections.sort(list); 

Come Morgano ha dichiarato correttamente, il metodo di ordinamento avrà una collezione che è parametrizzato con un tipo T che deve essere paragonabile a T. La tua classe MyItem si estende Item<String>, il che si traduce in MyItem essendo paragonabile a String s.

Con un piccolo interruttore in quale classe implementa l'interfaccia Comparable, si otterrà il risultato atteso:

public abstract class Item<T> { 
    protected T item; 
} 

public class MyItem extends Item<String> implements Comparable<MyItem> { 
    @Override 
    public int compareTo(MyItem o) { 
     return item.compareTo(o.item); // just an example 
    } 
} 

E ora la chiamata a Collections.sort(list) funzionerà.

1

basta cambiare la classe come segue:

 public class MyItem<T> extends Item<String> implement Comparable<MyItem<T>> 
    { 
     T object; 
    } 

O

 public abstract class Item<T> implements Comparable<MyItem<T>> 
     { 
      protected T item; 

      public int compareTo(MyItem<T> o) 
      { 
       return 0; // this doesn't matter for the time being 
     } 

}

Le punte di errore ha dimostrato us.Hope utile.

2

Per gli oggetti di tipo X per essere comparabili tra loro, la classe X deve essere implementata esattamente con Comparable<X>.

Questo non è ciò che sta facendo il tuo codice, hai una classe Item<T> e stai implementando Comparable<T> invece di Comparable<Item<T>>. Ciò significa che Item<T> può essere confrontato con T, ma non con Item<T>, che è richiesto.

cambiare classe Item<T> a:

public abstract class Item<T> implements Comparable<Item<T>> 
{ 
    protected T item; 

    @Override 
    public int compareTo(Item<T> o) 
    { 
     return 0; // this doesn't matter for the time being 
    } 
} 
+0

"Per gli oggetti di tipo X per essere comparabili tra loro, la classe X deve implementare esattamente il valore comparabile ." Non necessariamente esattamente. X potrebbe implementare 'Comparable ' – newacct

+0

@newacct Oh, giusto, certo. – Dukeling

Problemi correlati