Java / Scala Reflection: Holen Sie Klassenmethoden in die richtige Reihenfolge und erzwingen Sie Objekt-Init

8

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:

  • in der Reihenfolge, in der sie definiert sind
  • auf threadsichere Weise
  • filtere sie nach einem Super-Typ
  • und gierig initialisieren die Objekte (Verweis auf URLClassLoader ) ?

Aktualisieren :

  • Schlage keine Antworten basierend auf den Links hier vor, sie wurden getestet und sind bekannt dafür, dass sie scheitern.
  • Die Verwendung von 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.
flavian 14.03.2014, 13:03
quelle

4 Antworten

5

Von Ссылка :

  

öffentliches Feld [] getDeclaredFields ()                            löst SecurityException

aus      

Gibt 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.

Aktualisieren

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.

    
espenhw 18.03.2014, 11:46
quelle
0

AFAIK, das ist unmöglich. Die Member der Auftragsklasse sind einfach definiert und werden nicht in den .class -Dateien gespeichert (zumindest mit Java-Reflektion).

    
Alexey Romanov 14.03.2014 13:22
quelle
0

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. )

: -)

    
Glen Best 20.03.2014 06:36
quelle
0

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.

    
mike 09.03.2016 18:46
quelle

Tags und Links