Ich bin nicht wirklich vertraut mit den Klassenpfad-Scanner, die andere vorschlagen. Sie scheinen eine robuste - wenn nicht ideale - Lösung zu sein.
Wenn Sie die Kontrolle über die Quelle haben, können Sie die Annotationsverarbeitung verwenden.
Erstellen Sie einen Annotationsprozessor, der eine Klasse - MapClass
mit einem statischen Element Map<String,Foo>
erstellt. Jedes Mal, wenn der Annotationsprozessor auf die Annotation @Name stößt, fügt er diese dem Quellcode MapClass
hinzu. Wenn die Verarbeitung der Anmerkungen abgeschlossen ist, hat dies denselben Effekt, als ob Sie die Karte fest codiert hätten.
Die Annotationsverarbeitung erfolgt während der Kompilierungszeit. Wenn einige der Klassen in Ihrem Projekt nicht von Ihnen kompiliert werden. Zum Beispiel, wenn jemand anderes einige Klassen kompiliert und Ihnen ein Glas gibt, dann wird es nicht so einfach funktionieren. Aber wenn alle Klassen von Ihnen kompiliert werden, sollte das kein Problem sein.
Um einen Annotationsprozessor zu erstellen, erweitern Sie AbstractProcessor
. Sie sollten Ihre Klasse mit einer @ SupportedAnnotationTypes ("Name")
Annotation annotieren (stellen Sie sicher, dass name der vollständig qualifizierte Name Ihrer Annotation ist).
Überschreiben Sie die process
Methode. process
hat zwei Parameter: annotations
und roundEnv
. annotations
ist nur der Satz von Anmerkungen, die dieser bestimmte Prozessor unterstützt - in Ihrem Fall sollte es (Name) sein. roundEnv
ist eine nützliche Dienstprogrammklasse.
Iterieren Sie durch die eine Anmerkung in annotations
. Verwenden Sie roundEnv
bis getElementsAnnotatedWith
. Dies sollte Ihnen die Menge aller Elemente geben, die die @Name
Annotation tragen.
AbstractProcessor
hat ein anderes Dienstprogramm Mitglied - processingEnv
. Verwenden Sie die getFiler
-Methode zu createSourceFile
.
Dann müssen Sie Ihre Zusammenstellung ein wenig ändern. Sie müssen Ihren Prozessor separat und vor den anderen Klassen kompilieren. Nachdem der Prozessor kompiliert wurde und Sie die anderen Klassen kompilieren, müssen Sie den Compiler über Ihren Prozessor informieren. Wenn Sie die Befehlszeile verwenden, fügen Sie -processorpath /path/to/processor/class[es]
und -processor qualified.name.of.processor
hinzu.
Die Vorteile dieses Ansatzes gegenüber dem Klassenpfad-Scanner sind, dass alles zur Kompilierzeit passiert. Wenn Sie beispielsweise versehentlich eine @Name
Annotation zu einem Bar
Element hinzufügen, kann der Prozessor einen Kompilierzeitfehler auslösen (wenn Sie möchten, dass der Prozessor ihn ignorieren kann). Dann können Sie es reparieren, bevor das Produkt versendet. Bei einem Klassenpfad-Scanner ist jeder Fehler ein Laufzeitfehler - der dem Benutzer angezeigt wird.
Der Nachteil dieses Ansatzes ist auch, dass alles zur Kompilierzeit passiert. Dies erschwert das dynamische Hinzufügen von Klassen zum Projekt.
In Java? Unix cmd Zeile verwenden sollte ziemlich einfach mit find + grep – ControlAltDel
@ user1291492 sein, die Beibehaltung ist RUNTIME. Die Methode kann Zugriff auf den Quellcode haben oder nicht. OTH, vielleicht ist die Klassendatei übergreifbar. – emory
Etwas off-topic, aber warum willst du ein 'Set'. Es scheint sinnvoller zu sein, eine "Map " oder was ist der Sinn des Namens zu haben. –
emory