Ich habe ein class
mit ein paar Objekten als innere Methoden.
Ich habe auch gefragt diese Frage vor einer Weile und bekam eine gute Antwort, aber das führt zu fatalen Fehlern in Servlet-Containern. Scala kann nicht konsistent ein TypeTag
generieren, wenn% code_% nach einer Klasse fragt.
Das betreffende Projekt ist Open-Source und wurde hier gefunden.
Der aktuelle Ansatz findet sich hier , aber es bewahrt nicht die Ordnung. Objektmitglieder werden korrekt initialisiert, aber in zufälliger Reihenfolge.
Frage : Wie können Sie Klassenmitglieder sammeln:
URLClassLoader
)
? Aktualisieren :
module.instance
anstelle von val
ist aus stilistischen Gründen keine Option. object
oder getMethods
ist dafür bekannt, die Reihenfolge nicht zu garantieren. Wenn das irgendwie möglich ist, ist es wahrscheinlich mit Scala Reflektion. Von Ссылка :
öffentliches Feld [] getDeclaredFields () löst SecurityException
ausGibt ein Array von Field-Objekten zurück, die alle von der Klasse oder der Schnittstelle deklarierten Felder reflektieren repräsentiert durch dieses Klassenobjekt. Dazu gehören öffentliche, geschützte, Standard (Paket) Zugriff und private Felder, schließt jedoch vererbte Felder aus. Die Elemente im zurückgegebenen Array sind nicht sortiert und sind nicht in einer bestimmten Reihenfolge. Diese Methode gibt ein Array der Länge 0 zurück, wenn die Klasse oder die Schnittstelle deklariert keine Felder oder wenn dieses Klassenobjekt einen primitiven Typ, eine Array-Klasse oder void darstellt. Siehe die Java-Sprachspezifikation, Abschnitte 8.2 und 8.3.
(meine Betonung). Eine ähnliche Sprache ist explizit in der Dokumentation für getDeclaredMethods (), aber nicht in der für getDeclaredClasses () (aber IMO kann dort als implizit betrachtet werden).
Also nein, Sie können sich nicht darauf verlassen, dass Sie Java-Reflektionen auf der JVM bestellen; In der Praxis habe ich gesehen, dass die Reihenfolge je nach der Architektur der laufenden JVM variiert (32- gegenüber 64-Bit).
Wenn Sie die Objekte wirklich in einer bestimmten Reihenfolge initialisieren müssen (warum?), können Sie eine Benennungskonvention verwenden und manuell sortieren. Es wäre jedoch wahrscheinlich besser, den Code so zu ändern, dass er unabhängig von der Reihenfolge ist.
Es scheint, dass Sie möglicherweise etwas von der Scala-Reflektions-API erhalten:
%Vor%Siehe die API-Dokumentation :
Sortiert die in diesem Bereich enthaltenen Symbole so, dass: 1) Symbole in der Linearisierungsreihenfolge ihrer Besitzer angezeigt werden. 2) Symbole mit demselben Besitzer erscheinen in der gleichen Reihenfolge ihrer Deklarationen. 3) Synthetische Elemente (z.B. Getter / Setter für Vals / Vars) können in willkürlicher Reihenfolge erscheinen.
Dies funktioniert jedoch nicht garantiert, insbesondere für gemischte Java / Scala-Projekte (da es wirklich keine Möglichkeit gibt, Mitglieder einer Java-Klasse in die Deklarationsreihenfolge zu bringen). Beachten Sie außerdem, dass die Scala-Laufzeitreflexion nicht Thread-sicher ist und im Allgemeinen nicht als produktionsbereit betrachtet wird.
Ich habe immer noch das Gefühl, dass es besser wäre, wenn Sie Ihr Design so ändern, dass es unabhängig von der Reihenfolge ist, möglicherweise indem Sie die Abhängigkeiten anders kodieren.
AFAIK, das ist unmöglich. Die Member der Auftragsklasse sind einfach definiert und werden nicht in den .class
-Dateien gespeichert (zumindest mit Java-Reflektion).
Sie haben eine Klasse mit ein paar inneren object
s. Wie Sie angeben, werden innere Objekte lazy-initialisiert , wenn ein anderer Code sie referenziert / aufruft (ähnlich wie lazy val
).
Problem: (a) vorerwähnte lazy-initialization PLUS (b) implizite gegenseitige Abhängigkeiten zwischen den Objektdefinitionen. Dies bedeutet, dass sie in der Reihenfolge ihrer Abhängigkeitskette initialisiert werden müssen, aber nicht explizit aufeinander verweisen, so dass eine korrekt geordnete Lazy-Initialisierung nicht automatisch erfolgt.
Lösungsversuch: Initialisieren Sie diese Objekte programmatisch vor der Initialisierung in der richtigen Reihenfolge, indem Sie die Reflexion während der Konstruktions- / Initialisierungsphase verwenden. Während dies funktionieren würde, wenn Scala oder Java Reflektion mit dir zusammen arbeiten würde, "geht es gegen den Strich" - es widerspricht der Definition der inneren Objekte. Wenn Sie nicht möchten, dass sie faul initialisiert werden, warum sollten Sie sie dann als innere Objekte deklarieren?
Meine vorgeschlagene Lösung: Ändere die Deklarationen von inner object
s zu val
s. Bestellen Sie diese Deklarationen gemäß der gewünschten Initialisierungssequenz. Keine Reflexion erforderlich.
(Nebenbei: In diesem Zusammenhang haben Sie keine künstliche Einschränkung oder einen Grund erwähnt, warum object
s verwendet werden muss. Allerdings wenn ein seltsamer Grund für Sie besteht Sie müssen das Objekt verwenden, dann können Sie immer noch die Reflexion vermeiden, indem Sie einfach den Konstruktor jedes Objekts eine Methode forceInit
von jedem Objekt aufrufen, auf das es ankommt.Jede Methode forceInit
könnte einfach 1 zurückgeben. Dies würde die Lazy-Initialisierung in der richtigen Reihenfolge auslösen. )
: -)
Ich stieß auf ein ähnliches Problem und verwendete Anmerkungen mit einem gewissen Wert, um die Reihenfolge zu bestimmen. Insbesondere führt mein Objektmodell eine SWT-Tabelle, so dass ich erstellt:
%Vor% Dann beschriften Sie die Felder mit @DefaultColumnPosition(0)
oder was auch immer die Zahl ist. Sortiere nach den Werten. Es gibt ein wenig Overhead und es wäre besser, wenn es eine andere Methode oder vielleicht eine Annotation auf Klassenebene gäbe, die die Reihenfolge erzwingt, aber nicht so aussieht.
Ich habe die Scala-Lösung nicht ausprobiert, aber es sieht auch interessant aus, ich kann das eine Chance geben.
Tags und Links scala java reflection phantom-dsl