2015-06-01 6 views
6

Ich habe eine eher zentrale Klasse, die für einige Utility-Methoden zuständig ist. Ich wollte eine zusätzliche Überlast für ein Verfahren bereitzustellen, das wie folgt erklärt:Löschen von Sammlungen Generika und konfliktbehaftete Überladungen

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

Jetzt, da ich wie Rawtypes nicht wirklich tun, ich die Sammlungen in den kleinsten gemeinsamen Nenner angegeben aus kann ich erwarten:

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

So weit so gut, das hat die Rawtypes Warnung losgelassen und alles ist in Ordnung bis jetzt.

Ich ging die Methode Header für meine Überlastung zu schreiben:

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

Dies ist, wenn Eclipse (und anschließend mit javac6 über ant kompilieren) gab mir folgende Fehlermeldung:

Erasure von Methode removeDuplicated(Collection<T>, Collection<? extends Map<?,?>>) ist das gleiche wie eine andere Methode im Typ [Utilites-Klasse]

Jetzt seit ich hatte schon meinen Anteil von Pro Probleme mit Platzhalter-Generika und deren Löschungen Ich habe versucht, Dinge komplett zu spezifizieren, indem ich die ungebundenen Platzhalter durch Object ersetzte. Die Fehlermeldung bleibt weiterhin bestehen.

Nun, wie ich es verstehe, sollte die erste vorhandene Überladung zu Collection<Map<Object, Object>> löschen und die zweite sollte zu Collection<TeObjectWrapper> löschen.

Die einzige Möglichkeit, dass die gleiche Löschung sein könnte, ist, wenn TeObjectWrapper Map implementiert (oder eine der Implementierungsklassen von Map erweitert), aber das ist nicht der Fall. Das kann in der Hierarchie übergeordneter Typ von TeObjectWrapper zu sehen:

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

Warum der Compiler betrachten die Löschungen gleich und wie kann ich ihm das nicht denken?

+4

Die Löschung von 'Collection ' ist 'Collection'. –

+0

Aufgrund des Löschens ist die Methodensignatur identisch. Das Mischen mit den Generika ändert die Methodensignatur nicht. – user489041

Antwort

6

Beide löschen zu public static void removeDuplicated(Collection, Collection). Die gesamte Parametrierung ist gelöscht. Sie müssen ihnen verschiedene Namen geben.

Von 4.6. Type Erasure:

Typ Löschung ist eine Abbildung [...], um Typen (die nie parametrisierte Typen oder geben Sie Variablen sind).

Typ löscht auch die Signatur eines Konstruktors oder einer Methode auf eine Signatur mit keine parametrisierten Typen oder Variablen.

Erasure bedeutet: alles generische verschwindet.

(Aber als interessante Randnotiz, die allgemeinen Informationen istpresent in the class file. Die Überlastregel auf die Art und Weise zurückzuführen ist, die Spezifikation für Java gegeben ist, nicht unbedingt, weil es technisch nicht möglich ist. Es ist eher ein rückwärts Kompatibilitätsfunktion, um es älteren nicht generischen Klassen zu ermöglichen, generische Methoden zu überschreiben.Wenn Rohtypen in einer zukünftigen Version der Sprache entfernt wurden, könnten Überladungen wie diese erlaubt sein.)

+0

Ich glaube nicht, dass Rawtypes hier die Wurzel des Problems sind, aber die Entscheidung, Generika nicht verifizierbar zu machen (und sie entsprechend zu löschen) ist. Damit dieser Code so funktioniert, wie ich es mir vorgestellt habe, müssten Generika verifizierbar sein ... – Vogel612

+0

Die Überladungsauswahl wird statisch zur Kompilierungszeit durchgeführt, so dass keine vollständigen verifizierbaren Generika benötigt werden, um dies möglich zu machen. Die wahren Beschränkungen des Löschens haben mehr damit zu tun, was wir mit einer Typvariablen tun können, z. Wenn wir eine 'Klasse MyClass {...}' haben, können wir niemals Sachen wie 'new T()' und 'obj instanceof T' machen, da ein' MyClass 'und ein' MyClass 'zu den gleichen Bytecodes kompilieren. – Radiodef