Vorwort
Der gesamte Code in diesem Artikel ist in JavaScript geschrieben. Sie können jedoch auch andere JSR 223-kompatible Skriptsprachen verwenden. Diese Beispiele können als Skriptdateien oder in interaktiven Shells ausgeführt werden, indem jeweils eine Anweisung ausgeführt wird. Die Syntax für den Zugriff auf Eigenschaften und Methoden von Objekten in JavaScript ist die gleiche wie die der Java -Sprache.
Dieser Artikel enthält die folgenden Teile:
1. Zugriff auf Java -Klassen
Um auf native Typen oder Referenz -Java -Typen in JavaScript zuzugreifen, können Sie die Funktion Java.type() aufrufen, die den Typ des entsprechenden Objekts basierend auf dem in vollständigen Klassennamen übergebenen Bestandteil zurückgibt. Der folgende Code zeigt, wie verschiedene Objekttypen abgerufen werden:
var arrayList = java.type ("java.util.ArrayList"); var inttype = java.type ("int"); var stringarraype = java.type ("java.lang.String []); Die Methode zur Rückgabe eines Typobjekts mit Java.type() in JavaScript ähnelt der in Java.
Beispielsweise können Sie eine Klasse mit der folgenden Methode instanziieren:
var anarrayList = new java.type ("java.util.ArrayList");Java -Typobjekte können verwendet werden, um Java -Objekte zu instanziieren. Der folgende Code zeigt, wie ein neues Objekt mit dem Standardkonstruktor instanziiert und den Konstruktor aufruft, der die Parameter enthält:
var arrayList = java.type ("java.util.ArrayList"); var defaultSizearrayList = new ArrayList; var appenthSizearrayList = new ArrayList (16); Sie können Java.type() verwenden, um den Objekttyp zu erhalten, und die folgenden Methoden zum Zugriff auf statische Eigenschaften und Methoden:
var file = java.type ("java.io.file"); file.createTempile ("nashorn", ".tmp"); Wenn Sie auf die interne statische Klasse zugreifen möchten, können Sie das Dollar -Zeichen $ $ an Java.type() übergeben.
Der folgende Code zeigt, wie die Innenklasse von java.awt.geom.Arc2D Float -Innenklasse zurückgibt:
var float = java.type ("java.awt.geom.arc2d $ float");Wenn Sie bereits über ein externes Klassentyp -Objekt verfügen, können Sie wie unten auf die Eigenschaft zugreifen, genau wie Sie auf die Eigenschaft zugreifen würden:
var arc2d = java.type ("java.awt.geom.arc2d") var float = arc2d.floatDa es sich um eine nicht statische innere Klasse handelt, muss die externe Klasseninstanz als Parameter an den Konstruktor übergeben werden.
Obwohl die Verwendung von Typ -Objekten in JavaScript der in Java ähnlich ist, unterscheidet sich es immer noch etwas vom Objekt von java.lang.Class . Dieser Unterschied ist der Rückgabewert getClass() -Methode. Sie können class und static Eigenschaften verwenden, um diese Informationen zu erhalten.
Der folgende Code zeigt den Unterschied zwischen den beiden:
var arrayList = java.type ("java.util.ArrayList"); var a = new ArrayList; // Alle der folgenden Aussagen sind wahr: print ("Typ wirkt als Ziel von Instanz:" + (a Instanz von Arraylist); Print ("Class nicht wie Ziel von Instanz:" + [a InstanceOf A.GetClast)))). " + (a.getClass ()!Syntax und Semantik, Ausdrücke von JavaScript -Klassen und Laufzeitobjekte ähneln der Java -Semantik. In Java hat das Klassenobjekt jedoch keine Eigenschaft mit dem Namen statisch, da der kompilierte Klassenausdruck nicht als Objekt verwendet wird.
2. Importieren Sie Java -Pakete und Klassen
Um auf Java -Klassen basierend auf seinem einfachen Namen zugreifen zu können, können wir importPackage() und importClass() verwenden, um Java -Pakete und -klassen zu importieren. Diese Funktionen existieren in der Kompatibilitätskriptdatei (Mozilla_Compat.js).
Das folgende Beispiel zeigt, wie importPackage() und importClass() verwendet werden:
// Ladekompatibilitätskript laden ("Nashorn: Mozilla_Compat.js"); // Importieren Sie die Java.awt PackageImportpackage (Java.awt); // Importieren Sie die Java.awt.Frame ClassimportClass (java.awt.frame). methodFrame.setvisible (true); // Zugriff auf einen javabäischen PropertyPrint (Frame.Title); Java -Pakete können über die globale Variable der Pakete wie Packages.java.util.Vector oder Packages.javax.swing.JFrame zugegriffen werden. Das Standard -Java SE -Paket hat jedoch einfachere Zugriffsmethoden wie: Java entspricht Paketen.java, Javax entspricht Paketen.javax und org entspricht paket.org.
Das Java.lang-Paket erfordert standardmäßig nicht importiert, da dies mit anderen integrierten JavaScript-Objekten wie Object , Boolean und Math steht. Darüber hinaus kann das Importieren von Java -Paketen und -klassen auch variable Namenskonflikte im Rahmen des globalen Umfangs von JavaScript verursachen. with Konfl.
// Erstellen Sie ein Javaimporter -Objekt mit angegebenen Paketen und Klassen, um GUI = New Javaimporter (Java.awt, Javax.swing); // Übergeben Sie das Javaimporter -Objekt an die "Aussage" mit "Aussage" und greifen Sie auf die Klassen zu den Klassen // aus den importierten Paketen mit ihren einfachen Namen innerhalb der Anweisung der Anweisung zu greifen. var jframe = new Jframe ("Swing Jframe");};3. Verwenden Sie Java -Arrays
Um ein Java -Array -Objekt zu erstellen, müssen Sie zunächst das Java -Array -Objekt erhalten und initialisieren. Das Syntax- und length des JavaScript -Zugriffs auf Array -Elemente entspricht Java, wie im folgenden Code gezeigt:
var stringarray = java.type ("java.lang.String []"); var a = new StringArray (5); // Setzen Sie den Wert des ersten Elementa [0] = "Skription ist großartig!". Bei einem JavaScript -Array können wir es auch mit Java.to() in ein Java -Array umwandeln. Wir müssen das JavaScript -Array als Parameter an die Methode übergeben und den Typ des Arrays angeben, der zurückgegeben werden kann, der eine Zeichenfolge oder ein Typobjekt sein kann. Wir können auch die Typ -Objektparameter des Typs ignorieren, um das Objekt [] -Array zurückzugeben. Der Konvertierungsvorgang wird gemäß den ECMAScript -Konvertierungsregeln durchgeführt. Der folgende Code zeigt, wie ein JavaScript -Array in ein Java -Array durch verschiedene Java.to() -Parameter verwandelt wird:
// Erstellen Sie ein JavaScript -Array var anarray = [1, "13", false]; // Ein Array in Java int [] Array var javaintarray = java.to (anarray, "int []"); print (javaintarray [0]) konvertieren; // druckt die Nummer 1print (JavaintArray [1]); // druckt die Nummer 13print (JavaintArray [2]); // druckt die Nummer 0 // Javascript -Array in javastringArray = java.to (anarray, java.type ("java.lang.String []")); print (javastringArray [0]) konvertieren; // druckt die Zeichenfolge "1" drucken (JavastringArray [1]); // druckt den String "13" Print (JavastringArray [2]); // druckt die Zeichenfolge "False" // JavaScript -Array in Java -Objekt [] Array var javaObjectArray = java.to (anarray); print (JavaObjectArray [0]) konvertiert. // druckt die Nummer 1print (JavaObjectArray [1]); // druckt die Zeichenfolge "13" Print (JavaObjectArray [2]); // druckt den booleschen Wert "falsch". Sie können Java.from() verwenden, um ein Java -Array in ein JavaScript -Array umzuwandeln.
Der folgende Code zeigt, wie ein Array mit der Liste der Dateien im aktuellen Verzeichnis in ein JavaScript -Array konvertiert wird:
// Holen Sie sich den Java -Dateityp ObjectVar -Datei = java.type ("java.io.file"); // Erstellen Sie ein Java -Array von Dateiobjektsvar ListCurdir = new File ("). ArrayPrint (JSLIST);Beachten:
In den meisten Fällen können Sie Java -Objekte in Ihrem Skript verwenden, ohne sie in JavaScript -Objekte zu konvertieren.
4. Implementieren Sie die Java -Schnittstelle
Die Syntax der Implementierung von Java -Schnittstellen in JavaScript ähnelt der Methode zur Definition von anonymen Klassen in Java. Wir müssen nur die Schnittstelle instanziieren und ihre Methoden mit JavaScript -Funktionen implementieren.
Der folgende Code zeigt, wie die Runnable -Schnittstelle implementiert wird:
// Erstellen Sie ein Objekt, das die Runnable -Schnittstelle implementiert, indem // die Methode run () als JavaScript -Funktionsfunktion implementiert wird. }}; // Die R -Variable kann an Java -Methoden übergeben werden, die ein Objekt erwarten, das // die java.lang.runnable interfacevar th = new java.lang.thread (r); th.start (); th.join ();
Wenn eine Methode ein Objekt möchte, implementiert dieses Objekt eine Schnittstelle mit nur einer Methode, können Sie eine Skriptfunktion an diese Methode übergeben, anstatt das Objekt zu übergeben. Zum Beispiel benötigt Thread() -Konstruktor im obigen Beispiel ein Objekt, das Runnable -Schnittstelle als Parameter implementiert. Wir können die automatische Konvertierung nutzen, um eine Skriptfunktion an den Thread() -Konstruktor zu übergeben.
Das folgende Beispiel zeigt, wie ein Thread -Objekt erstellt wird, ohne eine Runnable Schnittstelle zu implementieren:
// Definieren Sie eine JavaScript -Funktionsfunktionsfunktion func () {print ("Ich bin func!");}; // Die JavaScript -Funktion anstelle eines Objekts übergeben, das // die java.lang.runnable interfacevar th = new java.lang.thread (func); th.start (); th.join (); Sie können mehrere Schnittstellen implementieren, indem Sie verwandte Typobjekte an Java.extend() weitergeben.
5. Erweitern Sie abstrakte Java -Klassen
Sie können eine anonyme Unterklasse der abstrakten Klassen -Unterklasse instanziieren. Übergeben Sie einfach ein JavaScript -Objekt an den Konstruktor, der einige Eigenschaften enthält, die den von der abstrakten Klassenmethode implementierten Werte entsprechen. Wenn eine Methode überlastet ist, liefert die JavaScript -Funktion Implementierungen aller Methodenvarianten. Das folgende Beispiel zeigt, wie eine Unterklasse des abstrakten Klassen -Timertasks initialisiert wird:
var timertask = java.type ("java.util.timerTask"); var task = new timerTask ({run: function () {print ("Hallo Welt!")}}); Neben dem Aufrufen des Konstruktors und der Übergabe von Parametern können wir auch Parameter direkt nach dem new Ausdruck bereitstellen.
Das folgende Beispiel zeigt, wie diese Syntax verwendet wird (ähnlich der Definition anonymer interner Klassen in Java), was etwas einfacher ist als das obige Beispiel:
var task = new timerTask {run: function () {print ("Hallo Welt!")}};Wenn die abstrakte Klasse eine einzelne abstrakte Methode (SAM -Typ) enthält, müssen wir kein JavaScript -Objekt an den Konstruktor übergeben, können wir eine Funktionsschnittstelle übergeben, die die Methode implementiert. Das folgende Beispiel zeigt, wie SAM -Typen verwendet werden, um den Code zu vereinfachen:
var task = new timerTask (function () {print ("Hallo Welt!")});Unabhängig von der von Ihnen ausgewählten Syntax können Sie Parameter in der Implementierungsobjekt und -funktion angeben, wenn Sie einen Konstruktor aufrufen müssen, der Parameter enthält.
Wenn Sie eine Java -Methode aufrufen möchten, für die SAM -Typ -Parameter erforderlich sind, können Sie eine JavaScript -Funktion an die Methode übergeben. Nashorn wird eine Unterklasse entsprechend den Anforderungen an die Methode instanziieren und diese Funktion verwenden, um die eindeutige abstrakte Methode zu implementieren.
Der folgende Code zeigt, wie Sie Timer.schedule() aufrufen, für die ein Timertask -Objekt als Parameter erforderlich ist:
var timer = java.type ("java.util.timer"); Timer.Schedule (function () {print ("Hallo Welt!")});Beachten:
Die vorherige Syntax geht davon aus, dass der erforderliche SAM -Typ eine Schnittstelle ist oder einen Standardkonstruktor enthält, den Nashorn zum Initialisieren einer Unterklasse verwendet. Dies ist nicht möglich, eine Klasse zu verwenden, die den Standardkonstruktor nicht enthält.
6. Erweitern Sie spezifische Java -Klassen
Um Verwirrung zu vermeiden, kann die Syntax für die Erweiterung abstrakter Klassen nicht zur Ausweitung von konkreten Klassen verwendet werden. Da eine konkrete Klasse instanziiert werden kann, wird eine solche Syntax in einen Versuch analysiert, eine neue Klasseninstanz zu erstellen und das vom Konstruktor erforderliche Objekt der Klasse zu übergeben (wenn der erwartete Objekttyp eine Schnittstelle ist). Um dieses Problem zu demonstrieren, sehen Sie sich bitte den folgenden Beispielcode an:
var t = new java.lang.thread ({run: function () {print ("thread running!")}}); Diese Codezeile wird analysiert, um die Thread -Klasse zu erweitern und run() -Methode zu implementieren, und die Instanziierung Thread -Klasse wird an seinen Konstruktor übergeben, ein Objekt, das die Runnable -Schnittstelle implementiert.
Um eine konkrete Klasse zu erweitern, übergeben Sie ihr Typobjekt an die Funktion Java.extend() und geben dann sein Typobjekt an seine Unterklasse zurück. Anschließend können Sie das Typobjekt dieser Unterklasse verwenden, um Instanzen zu erstellen und zusätzliche Methodenimplementierungen bereitzustellen.
Der folgende Code zeigt Ihnen, wie Sie Thread -Klasse erweitern und run() -Methode implementieren:
var thread = java.type ("java.lang.thread"); var threadextender = java.extend (thread); var t = new threadextender () {run: function () {print ("Thread running!")}}; Java.extend() kann eine Liste mehrerer Arten von Objekten abrufen. Sie können nicht mehr als ein Java -Typ -Objekt angeben oder die Anzahl der Typ -Objekte von bis zu Java -Schnittstellen angeben. Das zurückgegebene Typ -Objekt erweitert die angegebene Klasse (oder java.lang.Object , wenn es kein angegebenes Typ -Objekt gibt), implementiert diese Klasse alle Schnittstellen. Die Typobjekte der Klasse müssen nicht ganz oben auf der Liste stehen.
7. Methoden zum Zugriff auf Superklasse (übergeordnete Klasse)
Methoden, die auf die übergeordnete Klasse zugreifen möchten, können die Funktion Java .super() verwenden.
Das folgende Beispiel zeigt, wie java.lang.Exception erweitert wird und auf die Methoden der übergeordneten Klasse zugreift.
Beispiel 3-1 return _super_.getMessage (). touppercase (); }} try {throw -Exception;} catch (ex) {print (exception);}Wenn Sie den oben genannten Code ausführen, drucken Sie Folgendes:
jdk.nashorn.javaadapters.java.lang.Exception: Meine Ausnahmenachricht
8. Bindung an die Implementierung an die Klasse
Im vorherigen Abschnitt haben wir beschrieben, wie Java -Klassen erweitert und die Schnittstelle mithilfe eines zusätzlichen JavaScript -Objektparameters implementiert werden. Die Implementierung ist an einer bestimmten Instanz gebunden, die durch neue und nicht die gesamte Klasse erstellt wird. Dies gibt einige Vorteile, wie den Speicher Fußabdruck zur Laufzeit, da Nashorn einen einzigen Universaladapter für die Kombination von Typen jeder Implementierung erstellen kann.
Das folgende Beispiel zeigt, dass verschiedene Instanzen dieselbe Java -Klasse sein können, ihre JavaScript -Implementierungsobjekte jedoch unterschiedlich sind:
var runnable = java.lang.runnable; var r1 = new Runnable (function () {print ("Ich bin runnable 1!")}); var r2 = new Runnable (function () {print ("Ich bin runnable 2!")});Der obige Code druckt das folgende Ergebnis aus:
Ich bin runnable 1! Ich bin runnable 2! Wir teilen die gleiche Klasse: wahr
Wenn Sie eine Instanz einer Klasse an eine externe API übergeben möchten (z. B. das JavaFX -Framework, übertragen Sie eine Anwendungsinstanz an die Javafx -API), müssen Sie eine Java -Klasse erweitern oder eine an diese Klasse gebundene Schnittstelle implementieren. Sie können die Klasse implementieren, indem Sie eine JavaScript -Objektbindung übergeben und an den letzten Parameter der Funktion java.extend () weitergeben. Dadurch wird eine neue Klasse mit demselben Konstruktor wie die ursprüngliche Klasse erstellt, da sie keine zusätzliche Implementierung von Objektparametern erfordern.
Das folgende Beispiel zeigt, wie eine Implementierung in eine Klasse einbindet, und zeigt, dass die Implementierungsklassen für verschiedene Anrufe in diesem Fall unterschiedlich sind:
var runnableImpl1 = java.extend (java.lang.runnable, function () {print ("Ich bin runnable 1!")}); var runnableImpl2 = java.extend (java.lang.runnable, function () {print ("Ich bin runnable 2!")}); RunnableImpl2 (); r1.run (); r2.run (); print ("Wir teilen dieselbe Klasse:" + (r1.class === r2.class));Die obigen Beispielausführungsergebnisse sind wie folgt:
Ich bin runnable 1! Ich bin runnable 2! Wir teilen die gleiche Klasse: Falsch
Verschieben des Implementierungsobjekts aus dem Konstruktoraufruf in Java.extend() Vermeiden Sie die zusätzlichen Parameter, die im Konstruktoraufruf erforderlich sind. Jeder Aufruf zur Funktion Java.extend() erfordert ein Implementierungsobjekt der angegebenen Klasse, um eine neue Java -Adapterklasse zu generieren. Mit Klassengrenzen implementierte Adapterklassen können weiterhin einen zusätzlichen Konstruktorparameter verwenden, um das Verhalten einer bestimmten Instanz weiter zu überschreiben. Sie können also diese beiden Methoden zusammenführen: Sie können einen Teil der JavaScript -Implementierung in einer Basisklasse bereitstellen, sie dann an die Funktion Java.extend() weitergeben und eine Instanzimplementierung im Objekt angeben und an den Konstruktor weitergeben. Einige Funktionsdefinitionen des Objekts werden überschrieben, wenn das Objekt definiert und an den Konstruktor übergeben wird.
Der folgende Code zeigt, wie man eine Funktion eines Klassengrenzobjekts überschreibt, indem eine Funktion an den Konstruktor weitergegeben wird:
var runnableImpl = java.extend (java.lang.runnable, function () {print ("Ich bin runnable 1!")}); var r1 = new RunnableImpl (); var r2 = new RunnableImpl (function () {print ("Ich bin runnable 2!")}); (r1.class === r2.class));Die Druckergebnisse nach der Ausführung des obigen Beispiels sind wie folgt:
Ich bin runnable 1! Ich bin runnable 2! Wir teilen die gleiche Klasse: wahr
9. Wählen Sie Methodenüberlastvariante
Java -Methoden können durch Verwendung verschiedener Parametertypen überladen werden. Der Java Compiler (Javac) wählt die richtige Methode zum Kompilieren aus. Die Analyse von überlasteten Java -Methoden in Nashorn wird ausgeführt, wenn die Methode aufgerufen wird. Es ist auch eine Möglichkeit, die richtige Methode basierend auf dem Parametertyp zu bestimmen. Wenn der tatsächliche Parametertyp jedoch Unklarheiten verursacht, können wir explizit eine bestimmte überlastete Variante angeben. Dies verbessert die Leistung der Programmausführung, da die Nashorn -Engine nicht unterscheiden muss, welche Methode während des Anrufs aufgerufen werden soll.
Überladene Varianten werden als besondere Eigenschaften ausgesetzt. Wir können sie in Form von Zeichenfolgen verweisen, die Methodennamen und Parametertypen enthalten und von Klammern umgeben sind.
Das folgende Beispiel zeigt, wie System.out.println() mit Object Variante der Objektparameter aufgerufen wird.
var out = java.lang.System.out; out ["println (Objekt)"] ("Hallo");Im obigen Beispiel ist die Verwendung des Objektklassennamens allein ausreichend, da es sich um die Signatur handelt, die das richtige identifiziert. Der Fall, in dem Sie den vollständigen Klassennamen verwenden müssen, ist, dass zwei überlastete Variantenfunktionen unterschiedliche Parametertypen verwenden, der Typ jedoch denselben Namen hat (dies ist beispielsweise möglich, dass verschiedene Pakete denselben Klassennamen enthalten).
10. Zuordnen von Datentypen
Die überwiegende Mehrheit der früheren Conversions von Java und JavaScript funktioniert gut, wie Sie es erwarten würden. In den vorherigen Kapiteln haben wir einige einfache Datentyp -Zuordnungen zwischen Java und JavaScript erwähnt. Beispielsweise können Array -Typdaten explizit konvertiert werden. JavaScript -Funktionen können automatisch in SAM -Typen konvertiert werden, wenn sie als Parameter an Java -Methoden übergeben werden. Jedes JavaScript -Objekt implementiert die Schnittstelle java.util.Map , damit die API Mappings direkt akzeptiert. Wenn Sie Werte an die Java -API weitergeben, werden sie in den erwarteten numerischen Zieltyp konvertiert, der ein Kapselungstyp oder ein primitiver Datentyp sein kann. Wenn der Zieltyp nicht sehr sicher ist (wie z. B. Anzahl), können Sie nur den Zahlentyp benötigen und dann den Typ, z. B. Doppel, ganzzahl, lang, lang usw., spezifisch einkapseln. Die interne Optimierung macht den numerischen Wert eines beliebigen Paketarts. Kollegen, Sie können einen JavaScript -Wert an die Java -API übergeben, unabhängig davon, ob es sich um einen eingekapselten Typ oder einen primitiven Typ handelt, da der ToNumber -Konvertierungsalgorithmus von JavaScript den Wert automatisch verarbeitet. Wenn eine Java -Methode einen String oder Boolean -Objektparameter erfordert, verwendet JavaScript ToString und ToBoolean -Transformationen, um ihren Wert zu erhalten.
Beachten:
Aufgrund von Überlegungen zur internen Leistungsoptimierung für String -Operationen entsprechen JavaScript -Zeichenfolgen nicht immer dem Typ Java.lang.String, oder sie können auch java.lang.CharSequence sein. Wenn Sie eine JavaScript -String an eine Java -Methode übergeben, die den Parameter java.lang.String erfordert, ist die CharSequence -Zeichenfolge der Typ java.lang.String , aber wenn Ihre Methode Signatur generischer sein will (z. B. das akzeptierte Parametertyp ist Java.Lang.object.object), dann wird das Objekt.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Studium und die Arbeit aller Hilfe helfen. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen.