Il problema è che un Vettore<Integer> non è un Vettore<Comparable>, non lasciarti confondere dai generici.
Un Vettore<Comparable> può contenere qualunque tipo di oggetto che implementi Comparable (Integer, String, Double, quel che ti pare che implementa Comparable). Supponiamo, quindi, di avere un Vettore<Comparable> di questo tipo:
Vettore<Comparable> v = new Vettore<Comparable>();
v.add( 5 ); // Ammesso: Integer è Comparable
v.add( "Ciao" ) ; // Ammesso: String è Comparable
v.add( new Date() ); // Ammesso: Date è Comparable
Questo oggetto non contiene SOLO Integer, quindi è diverso da un Vettore<Integer> e non è nemmeno assegnabile (per ovvie ragioni). Quindi, Vettore<Integer> e Vettore<Comparable> sono oggetti completamente differenti.
Che succederebbe se fossero assegnabili? Bene... io ho un metodo che accetta un Vettore<Comparable> e gli passo un Vettore<Integer>. Chi mi vieta di fare questo?
Vettore<Integer> v = new Vettore<Integer>();
metodo( v );
...
public void metodo(Vettore<Comparable> v) {
v.add("Ciao");
}
Se io potessi passare il mio vettore di interi ad un metodo che accetta un vettore di Comparable, nessuno mi vieterebbe di "rovinare" il vettore inserendovi delle stringhe... e questo è assolutamente contrario ad ogni logica di type-checking.
Quello che serve a te è un modo per indicare al compilatore che il tuo metodo accetta un Vettore composto di tipi Comparable. E lo si fa con i bounded wildcard:
public static void bubbleSort(Vettore<? extends Comparable> v) {
... // Corpo del metodo
}
In questo caso, il metodo bubbleSort() accetterà qualunque vettore contenente dei comparable.
Ciao.