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:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Anschließend können Sie mit isAssignableFrom den Typ überprüfen.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Jedes Mal, wenn Sie Ihr Objekt instanziieren, müssen Sie sich wiederholen:
new MyCollection<Apples>(Apples.class);
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:
protected abstract void abstractMethod(T element);
Sie können es so verwenden:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
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.
Class.isAssignableFrom
.