2017-10-19 1 views
8

Ich habe folgende Klasse:Java - Verwenden Sie Class-Parameter in Methodenparameter

public class Publisher<T> { 

    private static final Class[] SUPPORTED_CLASSES = new Class[]{T1.class, T2.class}; 

    public Publisher() { 
     if(Arrays.asList(SUPPORTED_CLASSES).contains(T)) { // error: expression expected! 
      System.out.println("Class not supported!"); 
     } 
    } 
} 

Wie kann ich überprüfen, ob Klassenparameter für die Umsetzung entspricht?
Im obigen Beispiel kann ich den Klassenparameter T nicht als Parameter verwenden.

+0

Überprüfen Sie diesen Thread https://stackoverflow.com/questions/3403909/get-generic-type-of-class-at-runtime –

+3

Warum willst du das, wenn ich fragen darf? –

+0

@MCEperor Ich wollte überprüfen, ob die Klasse unterstützt wird, und ggf. eine Warnmeldung protokollieren. – FazoM

Antwort

13

Warum dies nicht

Sie arbeitet versuchen, einen generischen Typen zur Laufzeit zugreifen zu können, die wegen type erasure nicht in diesem Fall arbeiten.

Wie

Die einfachste Art und Weise zu beheben, um dieses Problem beheben ein Class<T> im Konstruktor zu nehmen ist, mit dem Sie den Typ zur Laufzeit gibt, können Sie überprüfen, ob die Liste den Wert enthält, die Sie erhalten haben .

Beispielcode

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

Mögliche Probleme

Ihr Code derzeit nicht Subtypen unterstützen, die Probleme verursachen können, wenn Sie mit dieser Ordnung sind (Sie auf Listen arbeiten kann, aber nicht unbedingt Arraylisten) , das tut Schnabel die LSP obwohl.

+0

Ich würde sagen, dass ein noch grundlegenderer Grund, warum der OP-Code nicht funktioniert, ist, dass Typargumente wie 'T' Typen * bezeichnen * keine Objekte.Insbesondere sind sie nicht gleich und stellen keine Objekte vom Typ 'java.lang.Class' dar, wie sie das Array des OP enthält. Typen sind keine gültigen gewöhnlichen Argumente. –

+0

LSP ist nur ein Problem, wenn die Klasse von OP in T kovariant sein soll. Wenn es kontra- oder invariant ist, ist dies eine völlig legale (wenn auch seltsame und nicht-OOP) Vorgehensweise. – Kevin

4

Sie benötigen die Klasse in den Konstruktor zu übergeben:

public Publisher(Class<T> clazz) { 
    if(!SUPPORTED_CLASSES.contains(clazz)) { 
     System.out.println("Class not supported!"); 
    } 
} 

weil T zur Laufzeit nicht verfügbar ist: genau der gleiche Code wird für new Publisher<T1>() und new Publisher<T3>() ausgeführt werden.

6

Obwohl einige andere Antworten recht gut sind, würde Ich mag eine andere Abhilfe vorzuschlagen:

Sie könnten eine leere Schnittstelle MyInterface, erstellen und alle Klassen in der Liste diese Schnittstelle implementieren. Dann können Sie Ihre Klassendeklaration ändern in:

public class Publisher<T extends S, MyInterface> 

die Ihren Zweck erfüllen wird.

+1

Dies ist eine bessere Lösung, wenn Sie die Kontrolle über alle Klassen haben, die Sie unterstützen müssen. Wenn Sie jedoch Klassen unterstützen müssen, die Sie nicht geschrieben haben, müssen Sie dies möglicherweise auf andere Weise tun. – jrtapsell

+1

@ jrtapsell im schlimmsten Fall, wenn Sie nicht zu viele Klassen unterstützen müssen, verwenden Sie eine Brücke für jede Klasse, die Sie brauchen (ein einfacher Wrapper), implementieren Sie die Schnittstelle – AxelH

+0

Wenn Ihre Lösung nur mit Klassen, die eine spezifische implementieren Englisch: www.doc-o-matic.com/webhelp/TdlgEditEdit.html Sie benötigen diese Liste der kompatiblen Klassen nicht mehr und können die Klasse einfach als public class Publisher 'deklarieren – Philipp

Verwandte Themen