2015-06-01 9 views
6

Ho una classe piuttosto centrale responsabile per alcuni metodi di utilità. Ho voluto fornire un sovraccarico aggiuntivo per un metodo che è stato dichiarato come segue:Cancellazione di generici di raccolte e sovraccarichi in conflitto

public static void removeDuplicated(Collection fullList, Collection itemsToRemove) { 
    //implementation stripped for brevity 
} 

Ora, poiché non mi piace molto Rawtypes, ho specificato le collezioni fuori nel minimo comune denominatore posso aspettarmi:

public static void removeDuplicated(Collection<Map<?,?>> fullList, 
    Collection<Map<?,?>> itemsToRemove) {} 

Fin qui tutto bene, questo ha eliminato l'avviso rawtype e tutto è andato bene fino ad ora.

ho provveduto a scrivere l'intestazione di metodo per il mio sovraccarico:

public static <T extends TeObjectWrapper> void removeDuplicated(
    Collection<T> fullList, Collection<Map<?,?>> itemsToRemove) {} 

Questo è quando eclisse (e successivamente la compilazione con javac6 via formica) mi ha dato errore seguente messaggio:

Erasure di metodo removeDuplicated(Collection<T>, Collection<? extends Map<?,?>>) è lo stesso di un altro metodo di tipo [Utility-Class]

Ora, poiché ho già avuto la mia parte di pro problemi con i generici di caratteri jolly e le loro cancellature Ho provato a specificare le cose completamente, sostituendo i caratteri jolly non associati con Object. Il messaggio di errore persiste ancora.

Da quanto ho capito, il primo sovraccarico esistente dovrebbe essere cancellato a Collection<Map<Object, Object>> e il secondo dovrebbe essere cancellato a Collection<TeObjectWrapper>.

L'unico modo in cui questi potrebbero essere la stessa cancellazione è se TeObjectWrapper ha implementato Map (o esteso una delle classi di implementazione di Map), ma non è questo il caso. Questo può essere visto nella gerarchia supertipo di TeObjectWrapper:

Supertype hierarchy: -TeObjectWrapper extends Object, implements <TeObjectAbstract implements TeBaseAbstract>

Perché il compilatore considera le cancellature lo stesso e come posso fargli Non pensate che?

+4

La cancellazione di 'Raccolta ' è 'Raccolta'. –

+0

A causa della cancellazione, la firma del metodo è la stessa. Pasticciare con i generici non cambia la firma del metodo. – user489041

risposta

6

Entrambi si riducono a public static void removeDuplicated(Collection, Collection). L'intera parametrizzazione viene cancellata. Dovrai dare loro nomi diversi.

Da 4.6. Type Erasure:

Tipo cancellazione è una mappatura [...] per i tipi (che sono tipi parametrizzati mai o variabili di tipo).

La cancellazione del tipo associa anche la firma di un costruttore o un metodo a una firma che ha nessun tipo parametrizzato o variabili di tipo.

Cancellazione significa: tutto generico scompare.

(Ma, come interessante side-nota, le informazioni generiche èpresent in the class file. La regola di sovraccarico è dovuto al modo in cui la specifica per Java è data, non necessariamente perché non è tecnicamente fattibile. E 'più di un all'indietro compatibilità, per consentire alle classi non generiche legacy di sovrascrivere i metodi generici.Se i tipi non elaborati sono stati rimossi in una versione futura della lingua, potrebbero essere consentiti sovraccarichi di questo tipo.)

+0

Non penso che i rawtype siano la radice del problema qui, ma la decisione di non rendere i generici reifiable (e di conseguenza cancellarli) è. Affinché questo codice funzioni come pensavo, Generics avrebbe bisogno di essere ridefinito ... – Vogel612

+0

La selezione del sovraccarico viene eseguita in modo statico al momento della compilazione, quindi non è necessario generare generici completi e reificabili per renderlo fattibile. Le vere limitazioni della cancellazione hanno più a che fare con ciò che possiamo fare con una variabile di tipo, ad es. se abbiamo un 'classe MyClass {...}' non possiamo mai fare cose come 'new T()' e 'obj instanceof T' perché un' MyClass 'e un' MyClass 'compile allo stesso bytecode. – Radiodef