Überprüfen ob übergebenes Objekt zu Generics passt

CptK

Bekanntes Mitglied
Hallo, ich habe folgende Struktur:

Java:
interface Label { String getName(); }

class LabelA extends Label {
    String getName() { return "LabelA"; }
}

class LabelB extends Label {
    String getName() { return "LabelB"; }
}

interface Parser { String getLabelName(); }

class ParserA {
    String getLabelName() { return "LabelA"; }
}

class ParserB {
    String getLabelName() { return "LabelB"; }
}

class X<L extends Label> {
    public X(Parser parser) {
        // Hier das Problem:
        if(parser.getLabelName() != L.getName())
            throw new ....
    }
}

Wie kann ich überprüfen, dass der übergebene Parser zu dem Label in den Generics passt? Also dass das hier durchgeht:
Java:
new X<LabelA>(new ParserA());
Folgende Sachen aber einen Fehler wefen:
Java:
new X<LabelB>(new ParserA());

new X<LabelA>(new ParserB());
 
Generics sind zur Laufzeit quasi nicht existent, die Information wird primaer nur beim kompilieren verwendet, bedeutet du kannst nicht direkt auf diese Informationen zugreifen.

Der Weg den mann in diesem Fall fuer gewoehnlich geht, ist es die Klasse zu uebergeben welche erlaubt oder erwartet ist.

Java:
public class X<L extends Label> {
    public X(Parser parser, Class<L> expectedLabelClass) {
        if(!parser.getLabelName().equals(expectedLabelClass.getSimpleName())) {
        }
    }
}

new X<LabelB>(new ParserB(), LabelB.class);

Was aber eine bessere Strukturierung waere, ist wenn du den Parser testen laesst ob dieser eine bestimmte Label-Klasse annehmen kann:

Java:
public interface Parser {
    public boolean accepts(Class<? extends Label> labelClass);
}

public class X<L extends Label> {
    public X(Parser parser, Class<L> expectedLabelClass) {
        if(!parser.accepts(expectedLabelClass)) {
        }
    }
}

new X<LabelB>(new ParserB(), LabelB.class);

Damit kann der Parser sehr einfach entscheiden ob er diese Klasse akzeptiert oder nicht.

Als Anmerkung: Erstens, Strings mit "==" zu vergleichen bedeutet du vergleichst die Referenz, also ob es sich um das selbe Objekt handelt. String-Konstanten sind zufaellig zur Laufzeit immer die selbe Instanz. Du willst Strings immer mit "equals" vergleichen (z.B. auch ueber Objects.equals() als Hilfe). Beispiel:

Java:
"ABC" == "ABC" // true

"ABC" == new String("ABC") // false

String value = "ABC";
value == "ABC" // true

new String("ABC") == "ABC" // false

new String("ABC").intern() == "ABC" // true

".intern()" in dem Fall retourniert die Instanz von diesem String aus dem globalen String-Cache, welcher dann wieder die selbe ist wie die Konstante.

Zweitens, wenn moeglich verwende immer Class-Instanzen und Referenzen anstelle von Strings. Das ist nicht immer moeglich (Klassen nicht bekannt zur Kompilierzeit und so weiter), aber wenn, ist es besser als Strings herum zu schieben.
 

Neue Themen


Zurück
Oben