Nashorn, Java-Sammlungen, Wie man equals und hashCode in reinem Javascript implementiert

8

Ich habe mit dem folgenden Problem konfrontiert. Ich möchte java.util.HashMap und java.util.PriorityQueue im Skript Nashorn verwenden, wo ich ein bestimmtes benutzerdefiniertes Objekt als Schlüssel in der HashMap verwenden muss, und auch% verwenden co_de%, um zu prüfen, ob ein Schlüssel in der Karte vorhanden ist (eine weitere Option besteht darin, zu prüfen, ob das Objekt in einer Sammlung enthalten ist (Objekt o)).

Also muss ich natürlich in meinem Objekt equals und hashCode implementieren, basierend auf einigen Feldwerten.

Zum Beispiel:

  1. Versuche, JavaScript zu verwenden. Funktioniert nicht, weil JavaScript diese Methoden nicht hat. Sehen Sie sich Beispiel 1 und Beispiel 2

  2. an
  3. Erweiterung von java.lang.Object Beispiel 3 Funktioniert teilweise, Methoden werden aufgerufen. Aber

    • Wie man Konstruktor mit Parametern einbettet?
    • Wie kann man die Umwandlung von diesem Objekt [object] zu einem anderen durchführen: jdk.nashorn.javaadapters.java.lang.Object@0 oder umgekehrt?
  4. Implementieren meiner benutzerdefinierten Klasse in Java und Erweitern in JavaScript. Beispiel 4 Funktioniert. Brauche ich Nashorn, wenn ich Java benutzen muss?

%Vor%

BEARBEITEN 1

@Tomasz, danke. Habe alle erwähnten Links gesehen. Aber obwohl das etwas undokumentiert existiert. Fast gab mit Nashorn auf. Zu der folgenden Teillösung kam es, Methoden werden aufgerufen, Konstruktor wird verwendet, aber wie HashMap.containsKey() in der other.from -Methode gecastet wird, um Zugriff auf das equals -Feld des ursprünglichen Objekts zu erhalten (Dieser Code erzeugt für jede Instanz eines Vertex unterschiedliche Klassen):

%Vor%

BEARBEITEN 2

Danke für Tomasz, wie er darauf hingewiesen hat: Jeder Aufruf der Funktion java.extend () mit einem klassenspezifischen Implementierungsobjekt erzeugt eine neue Java-Adapterklasse. Daher müssen wir einen Objekt-Extender haben und Objekte mit diesem einen Typ instanziieren, wie er in seinem Beispiel gezeigt hat. Ich habe es ein wenig modifiziert, so dass es Instanzen mit der gleichen Klasse entweder mit dem Factory- oder dem direkten Konstruktor erzeugt, da wir den gleichen Objekt-Extender verwenden

%Vor%

Es gibt jedoch noch ein Problem, der Typ des Parameters von from ist equals , mit anderen Worten, die jdk.nashorn.javaadapters.java.lang.Object und other innerhalb this sind unterschiedliche Typen. Gibt es eine Möglichkeit, equals -Wert aus dem Objekt zu generieren oder an _from zu übergeben?

DIE LÖSUNG

Siehe die Lösung für das Problem in der Antwort von Tomasz .

Tolle Arbeit Tomasz! Danke.

PS: Es ist sehr traurig, dass es in Nashorn keine einfache und direkte Möglichkeit gibt, equals und equals zu implementieren. Es wäre nützlich für das Prototyping. Vergleichen Sie das einfach mit diesem:)

%Vor%     
Arseny Kovalchuk 19.08.2014, 08:56
quelle

1 Antwort

6

In Rhino würden Sie verwenden:

%Vor%

Damit die JavaScript-Methoden die gleichnamigen Java-Methoden von java.lang.Object überschreiben (siehe Referenz Ссылка )

Vielleicht gibt es ein ähnliches Konstrukt in Nashorn.

BEARBEITEN:

Sie können die Rhino-Syntax in Nashorn verwenden. Setzen Sie einfach die Zeile:

%Vor%

Siehe: Ссылка

BEARBEITEN: (WIEDER)

Mit Nashorn scheint es viel komplizierter zu sein:

%Vor%

Siehe Ссылка

Was ist interessanter, wenn Sie mehrere Instanzen wie folgt erstellen:

%Vor%

Dann sind sie von der gleichen Klasse (ich erwartete, dass sie Instanzen von zwei anonymen Sonnenklas sen von Object sind).

%Vor%

EIN TRICK:

Obwohl du in Nashorn nicht-abstrakte Klassen im laufenden Betrieb erweitern kannst, wie:

%Vor%

Sie können auf diese Weise abstrakte Klassen oder Interfaces erweitern. (Und da jede anonyme Klasse, die eine Schnittstelle implementiert, auch Object erweitert, können Sie auch die Methoden equals oder hashCode überschreiben).

Um dies zu veranschaulichen, sollten Sie eine JavaScript-Prototyp-Klasse verwenden:

%Vor%

Sie können nun seine "Java-Wrapped" -Instanzen wie folgt erstellen:

%Vor%

Sie wissen, dass Sie eine leere Java-Schnittstelle erstellen können, um solche Wrapper zu aktivieren, ohne dass zusätzliche Methodenimplementierungen bereitgestellt werden müssen (wie compare im obigen Beispiel mit Comparable ).

PROBLEM

Wie Sie bereits erwähnt haben, handelt es sich bei den oben dargestellten Objekten um Java-Objekte mit fester "Schnittstelle". Daher wird jede Methode oder jedes Feld aus umgebrochenem JavaScript-Objekt, das nicht ausdrücklich von implementierten Interfaces oder Klassen spezifiziert wurde, NICHT von JavaScript aus zugänglich sein.

DIE LÖSUNG

Nach einigem Tüfteln fand ich die Lösung für das obige Problem. Ein Schlüssel dazu ist jdk.nashorn.api.scripting.AbstractJSObject class von Nashorn Scripting API.

Überlegen Sie, wir haben JSVertex "JavaScript-Klasse" (sehr ähnlich wie bereits oben dargestellt):

%Vor%

Lassen Sie uns eine Funktion erstellen, die es ermöglicht, Java-Objekte so über jedes JavaScript-Objekt zu legen, dass jede gleichnamige Methode aus dem JavaScript-Objekt die entsprechende Java-Objekt-Methode "erweitert".

%Vor%

Nachdem wir das alles geschrieben haben, sehen wir, dass es funktioniert.

Erstellen Sie einen Wrapper über das JSVertex-Objekt und führen Sie einige Tests durch:

%Vor%

Die Ausgabe:

%Vor%     
Tomasz Gawel 19.08.2014, 11:06
quelle