Bevor ich meine generische Datenstruktur nach dem Index eines Werts durchsuche, möchte ich sehen, ob es sich überhaupt um eine Instanz des Typs handelt, this
für den parametrisiert wurde.
Aber Eclipse beschwert sich, wenn ich das tue:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
Dies ist die Fehlermeldung:
Instanz der Prüfung für Typparameter E kann nicht durchgeführt werden. Verwenden Sie stattdessen das Löschobjekt, da generische Typinformationen zur Laufzeit gelöscht werden
Was ist der bessere Weg, um es zu tun?
quelle
Class.isAssignableFrom
.Zwei Optionen für die Überprüfung des Laufzeittyps mit Generika:
Option 1 - Beschädigen Sie Ihren Konstruktor
Nehmen wir an, Sie überschreiben indexOf (...) und möchten den Typ nur auf Leistung überprüfen, um sich die Iteration der gesamten Sammlung zu ersparen.
Machen Sie einen schmutzigen Konstruktor wie folgt:
Anschließend können Sie mit isAssignableFrom den Typ überprüfen.
Jedes Mal, wenn Sie Ihr Objekt instanziieren, müssen Sie sich wiederholen:
Sie könnten entscheiden, dass es das nicht wert ist. Bei der Implementierung von ArrayList.indexOf (...) wird nicht überprüft, ob der Typ übereinstimmt.
Option 2 - Lass es scheitern
Wenn Sie eine abstrakte Methode verwenden müssen, die Ihren unbekannten Typ erfordert, möchten Sie nur, dass der Compiler aufhört, über instanceof zu weinen . Wenn Sie eine Methode wie diese haben:
Sie können es so verwenden:
Sie wandeln das Objekt in T (Ihren generischen Typ) um, nur um den Compiler zu täuschen. Ihre Besetzung führt zur Laufzeit nichts aus , aber Sie erhalten trotzdem eine ClassCastException, wenn Sie versuchen, den falschen Objekttyp an Ihre abstrakte Methode zu übergeben.
HINWEIS 1: Wenn Sie in Ihrer abstrakten Methode zusätzliche ungeprüfte Casts ausführen, werden Ihre ClassCastExceptions hier abgefangen. Das könnte gut oder schlecht sein, also denke darüber nach.
HINWEIS 2: Sie erhalten eine kostenlose Nullprüfung, wenn Sie instanceof verwenden . Da Sie es nicht verwenden können, müssen Sie möglicherweise mit bloßen Händen nach Null suchen.
quelle
Alter Beitrag, aber eine einfache Möglichkeit, eine generische Instanz der Überprüfung durchzuführen.
quelle
Vorausgesetzt, Ihre Klasse erweitert eine Klasse mit einem generischen Parameter, können Sie diesen auch zur Laufzeit über Reflection abrufen und dann zum Vergleich verwenden, d. H.
Im obigen Fall erhalten Sie zur Laufzeit String.class von getParameterizedClass () und es wird zwischengespeichert, sodass Sie bei mehreren Überprüfungen keinen Reflexionsaufwand erhalten. Beachten Sie, dass Sie die anderen parametrisierten Typen per Index über die Methode ParameterizedType.getActualTypeArguments () abrufen können.
quelle
Ich hatte das gleiche Problem und hier ist meine Lösung (sehr bescheiden, @george: diesmal kompilieren UND arbeiten ...).
Mein Problem befand sich in einer abstrakten Klasse, die Observer implementiert. Das Update der Observable-Feuermethode (...) mit der Object-Klasse, die eine beliebige Art von Objekt sein kann.
Ich möchte nur Objekte vom Typ T behandeln
Die Lösung besteht darin, die Klasse an den Konstruktor zu übergeben, um zur Laufzeit Typen vergleichen zu können.
Für die Implementierung müssen wir nur die Klasse an den Konstruktor übergeben
quelle
Oder Sie könnten einen fehlgeschlagenen Versuch abfangen, in E zu zaubern, z.
quelle
Technisch gesehen sollten Sie das nicht müssen, das ist der Punkt von Generika, damit Sie die Überprüfung des Kompiliertyps durchführen können:
Aber dann kann der @Override ein Problem sein, wenn Sie eine Klassenhierarchie haben. Ansonsten siehe Yishais Antwort.
quelle
Der Laufzeittyp des Objekts ist eine relativ willkürliche Bedingung zum Filtern. Ich schlage vor, solchen Dreck von Ihrer Sammlung fernzuhalten. Dies wird einfach dadurch erreicht, dass Ihre Sammlung an einen Filter delegiert wird, der in einer Konstruktion übergeben wird.
quelle
Comparator