2009-01-20 7 views
5

Die Idee ist es, eine Basisklasse zu definieren, die in abgeleiteten Klassen definierte Methoden aufrufen kann, aber zum Zeitpunkt der Erstellung möchte ich sicherstellen, dass solche Methoden genau nach den Anforderungen definiert sind, dass die Methoden nur ein Argument nehmen, a HashMap <String String>.Java: Wie generische Klassentypdefinitionen überprüft werden?

Bis jetzt konnte ich mit dem folgenden Code überprüfen, dass die Methode nur einen Parameter enthält und dass es von Class HashMap ist, aber wie kann ich überprüfen, dass die generische Definition <String, String>?

public boolean isMethodParameterValid(final Method method) { 
    final Class<?>[] parameters = method.getParameterTypes(); 
    return ((parameters.length == 1) && parameters[0].isAssignableFrom(HashMap.class)); 
} 

Antwort

7

Sie können nicht. Generische Java-Typen werden vom Compiler "gelöscht", d. H. HashMap<String, String> wird zur Laufzeit nur HashMap. Siehe this Frage.

+1

Nicht alle Typen werden gelöscht. Ein anderes Beispiel wäre 'new ArrayList {}'. Neal Gafters Super Type Token Post ist ebenfalls lesenswert: http://gafter.blogspot.com/2006/12/super-type-tokens.html – johnstok

+0

Nein, Neals Gafters Super Type Token werden zur Kompilierzeit gelöscht. Sein Trick hilft beim Zugriff auf den Typ, mit dem das generische Objekt zur Laufzeit instanziiert wird (da Type.getClass() autorisiert ist). – JVerstry

1

Ich verstehe nicht wirklich das Ziel dessen, was Sie versuchen zu tun. Ich habe das Gefühl, dass es möglich sein sollte, dies zur Kompilierzeit zu überprüfen, indem Sie sorgfältig Ihre Klassenhierarchie entwerfen. Aber ohne weitere Details zu dem Problem, das Sie zu lösen versuchen, kann ich Ihnen nicht helfen.

1

Wie bereits erwähnt, können Sie zur Laufzeit nicht den generischen Teil eines Typs betrachten.

Gibt es einen Grund, dass Sie einfach eine abstrakte Methode wie im Template-Muster definieren können?

Dann wird die Überprüfung statisch durchgeführt.

protected abstract void process(HashMap<String, String>); 

(auch gibt es einen Grund HashMap über nur Karte zu verlangen?)

12

Tatsächlich gibt es Typ Löschung aber es ist nicht auf Variablen/Felder angewendet - nur Definitionen von Klassen, in denen die Art params werden gelöscht und durch ihre oberen Grenzen ersetzt.

Dies bedeutet, dass das, was Sie fordern, erreicht werden kann. So können Sie die generischen Parameter des ersten Parameters einer Methode überprüfen:

class Z 
{ 
    public void f(List<String> lst) { } 
} 

... 

Method m = Z.class.getMethod("f", List.class); 
Type t = m.getGenericParameterTypes()[0]; 
if(t instanceof ParameterizedType) { 
    ParameterizedType pt = (ParameterizedType) t; 
    System.out.println("Generic params of first argument: " + Arrays.toString(pt.getActualTypeArguments())); 
}  
+0

Ja. Wenn Sie eine Instanz einer Klasse haben, können Sie sie zur Laufzeit nicht nach ihren generischen Typparametern fragen. Wenn Sie ein reflektierendes Handle für eine Methode, Klasse oder ein Feld haben, das möglicherweise mit generischen Typparametern definiert wurde, können Sie mit Reflektionsmethoden entscheiden, was diese generischen Parameter sind - ob es sich um Typen, Platzhalter, Typvariablen usw. handelt. – pholser