Ist es möglich, alle Klassen zu erhalten, die eine Schnittstelle implementieren? [Duplikat]

8

Kann ich das mit Reflektion oder so machen?

    
Par 09.03.2013, 06:02
quelle

1 Antwort

9

Es gibt keine 100% zuverlässige Möglichkeit, das zu tun, was Sie wollen. Der Grund dafür ist, dass das Laden von Klassen in Java funktioniert.

Klassen in Java werden "on demand" geladen. Wenn eine Klasse zum ersten Mal im Code referenziert wird (entweder statisch oder dynamisch), verwendet die JVM den aktuellen Klassenlader und versucht, ihn zu laden. Ein ClassLoader hat keine Methode, die alle Klassen enthält, die von ihm geladen werden könnten. Daher können Sie Klassen nicht iterieren.

Es gibt einige unzuverlässige Problemumgehungen . Wenn Sie beispielsweise wissen, dass Ihr ClassLoader nur Klassen innerhalb eines bestimmten Verzeichnisses oder einer bestimmten JAR-Datei lädt, können Sie die Klassen Ihres Dateisystems verwenden, um herauszufinden, welche ".class" -Dateien verfügbar sind lade alles (was Zeit kostet und viel von deinem PermGen verbraucht, was ein Problem sein könnte) - erinnere dich daran, dass du eine Klasse nicht einfach entladen kannst (außer du magst etwas ClassLoader)) und benutze reflection, um die Klassen zu filtern, die deine implementieren Schnittstelle.

Das Problem mit dieser Problemumgehung ist, dass es wahrscheinlich nicht mehr funktioniert, wenn Sie Ihre Bereitstellung ändern. Wenn Sie beispielsweise mit der Bereitstellung einer JAR-Datei beginnen und später einen Servlet-Container verwenden, der sich mit WAR-Dateien befasst, funktioniert Ihr Code möglicherweise nicht mehr.

Wenn Sie diesen Ansatz wirklich ausprobieren möchten, gibt es ein Projekt namens Reflexionen könnte nützlich sein.

Die zuverlässigste Methode, die ich jemals implementiert habe, ist die Verwendung eines Annotation Processors . Sie schreiben eine Annotation, Sie kommentieren Ihre Schnittstelle und Sie schreiben einen Code, der vom Compiler während der Kompilierung ausgeführt wird, der die Klassen sammelt, die Ihre Schnittstelle implementieren, und ihre Namen in einer Ressourcendatei speichert. Dann schreiben Sie eine Klasse mit einer Methode, die diese Datei liest und Ihnen für jeden in dieser Ressourcendatei aufgeführten Klassennamen ein Klassenobjekt gibt.

Das Problem bei diesem Ansatz besteht darin, dass nur Klassen aufgelistet werden, die in meinem Build-Prozess kompiliert wurden (dh wenn Sie eine Bibliothek mit einer Schnittstelle veröffentlichen und von anderen erwarten, dass sie Ihre Schnittstelle implementieren), ist diese Vorgehensweise nicht sinnvoll Ihr Code wird nie von der Klasse in den Projekten anderer erfahren. Wenn das für Sie genug ist, wie für mich, funktioniert diese Lösung einwandfrei. Ich kann es in Servlet-Containern mit WAR-Installationen (explodiert oder nicht), in ausführbaren Jars, was auch immer, verwenden. Es wird immer funktionieren.

    
Bruno Reis 09.03.2013, 06:06
quelle

Tags und Links