JavaScript: The Definitive Guide, Sixth Editio javaScript权威指南(第6版) pdf 文字版-文字版, javascript电子书, 和javascript 有关的电子书:

12.1 Scripting Java with Rhino

12.1 Scripting Java with Rhino

Rhino is a JavaScript interpreter written in Java and designed to make it easy to write JavaScript programs that leverage the power of the Java platform APIs. Rhino automatically handles the conversion of JavaScript primitives to Java primitives, and vice versa, so JavaScript scripts can set and query Java properties and invoke Java methods.

Obtaining Rhino

Rhino is free software from Mozilla. You can download a copy from http://www.mozilla .org/rhino/ . Rhino version 1.7r2 implements ECMAScript 3 plus a number of the language extensions described in Chapter 11 . Rhino is mature software and new versions are not released often. At the time of this writing, a prerelease version of 1.7r3 is available from the source repository and includes a partial implementation of ECMAScript 5.

Rhino is distributed as a JAR archive. Start it with a command line like this:

java -jar rhino1_7R2/js.jar program.js

If you omit program.js, Rhino starts an interactive shell, which is useful for trying out simple programs and one-liners.

Rhino defines a handful of important global functions that are not part of core JavaScript:

// Embedding-specific globals: Type help() at the rhino prompt for more print(x); // Global print function prints to the console version(170); // Tell Rhino we want JS 1.7 language features load(filename,...); // Load and execute one or more files of JavaScript code readFile(file); // Read a text file and return its contents as a string readUrl(url); // Read the textual contents of a URL and return as a string spawn(f); // Run f() or load and execute file f in a new thread runCommand(cmd, // Run a system command with zero or more command-line args

[args...]); quit() // Make Rhino exit

Notice the print() function: we’ll use it in this section instead of console.log(). Rhino represents Java packages and classes as JavaScript objects:

// The global Packages is the root of the Java package hierarchy // Any package from the Java CLASSPATH java.lang // The global java is a shortcut for javax.swing // And javax is a shortcut for Packages.javax

// Classes: accessed as properties of packages var System = java.lang.System; var JFrame = javax.swing.JFrame;

Because packages and classes are represented as JavaScript objects, you can assign them to variables to give them shorter names. But you can also more formally import them, if you want to:

var ArrayList = java.util.ArrayList; // Create a shorter name for a class importClass(java.util.HashMap); // Same as: var HashMap = java.util.HashMap

// Import a package (lazily) with importPackage(). // Don't import java.lang: too many name conflicts with JavaScript globals.

importPackage(java.util); importPackage(;

// Another technique: pass any number of classes and packages to JavaImporter() // and use the object it returns in a with statement var guipkgs = JavaImporter(java.awt, java.awt.event, Packages.javax.swing); with (guipkgs) {

/* Classes like Font, ActionListener and JFrame defined here */ }

Java classes can be instantiated using new, just like JavaScript classes can:

// Objects: instantiate Java classes with new var f = new"/tmp/test"); // We'll use these objects below var out = new;

Rhino allows the JavaScript instanceof operator to work with Java objects and classes:

f instanceof // => true out instanceof // => false: it is a Writer, not a Reader out instanceof // => true: Writer implements Closeable

As you can see, in the object instantiation examples above, Rhino allows values to be passed to Java constructors and the return value of those constructors to be assigned to JavaScript variables. (Note the implicit type conversion that Rhino performs in this example: the JavaScript string “/type/test” is automatically converted into a Java java.lang.String value.) Java methods are much like Java constructors, and Rhino allows JavaScript programs to invoke Java methods:

// Static Java methods work like JavaScript functions java.lang.System.getProperty("java.version") // Return Java version var isDigit = java.lang.Character.isDigit; // Assign static method to variable

// => true: Arabic digit 2")isDigit("

// Invoke instance methods of the Java objects f and out created above out.write("Hello World\n"); out.close(); var len = f.length();

Rhino also allows JavaScript code to query and set the static fields of Java classes and the instance fields of Java objects. Java classes often avoid defining public fields in favor of getter and setter methods. When getter and setter methods exist, Rhino exposes them as JavaScript properties:

// Read a static field of a Java class var stdout = java.lang.System.out;

// Rhino maps getter and setter methods to single JavaScript properties // => "/tmp/test": calls f.getName() // => false: calls f.isDirectory()

Java allows overloaded methods that have the same name but different signatures. Rhino can usually figure out which version of a method you mean to invoke based on the type of the arguments you pass. Occasionally, you need to specifically identify a method by name and signature:

12.1 Scripting Java with Rhino | 291

// Suppose the Java object o has a method named f that expects an int or // a float. In JavaScript, you must specify the signature explicitly: o['f(int)'](3); // Call the int method o['f(float)'](Math.PI); // Call the float method

You can use a for/in loop to iterate through the methods, fields, and properties of Java classes and objects:

importClass(java.lang.System); for(var m in System) print(m); // Print static members of the java.lang.System for(m in f) print(m); // Print instance members of

// Note that you cannot enumerate the classes in a package this way for (c in java.lang) print(c); // This does not work

Rhino allows JavaScript programs to get and set the elements of Java arrays as if they were JavaScript arrays. Java arrays are not the same as JavaScript arrays, of course: they are fixed length, their elements are typed, and they don’t have JavaScript methods like slice(). There is no natural JavaScript syntax that Rhino can extend to allow JavaScript programs to create new Java arrays, so you have to do that using the java.lang.reflect.Array class:

// Create an array of 10 strings and an array of 128 bytes var words = java.lang.reflect.Array.newInstance(java.lang.String, 10); var bytes = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 128);

// Once arrays are created, you can use them much like JavaScript arrays: for(var i = 0; i < bytes.length; i++) bytes[i] = i;

Java programming often involves implementing interfaces. This is particularly common in GUI programing, where each event handler must implement an event listener interface, and the following examples demonstrate how to implement Java event listeners:

// Interfaces: Implement interfaces like this:

var handler = new java.awt.event.FocusListener({ focusGained: function(e) { print("got focus"); }, focusLost: function(e) { print("lost focus"); }


// Extend abstract classes in the same way var handler = new java.awt.event.WindowAdapter({ windowClosing: function(e) { java.lang.System.exit(0); } });

// When an interface has just one method, you can just use a function instead button.addActionListener(function(e) { print("button clicked"); });

// If all methods of an interface or abstract class have the same signature, // then you can use a single function as the implementation, and Rhino will // pass the method name as the last argument frame.addWindowListener(function(e, name) {

if (name === "windowClosing") java.lang.System.exit(0); });

// If you need one object that implements multiple interfaces, use JavaAdapter: var o = new JavaAdapter(java.awt.event.ActionListener, java.lang.Runnable, {

run: function() {}, // Implements Runnable

actionPerformed: function(e) {} // Implements ActionListener


When a Java method throws an exception, Rhino propagates it as a JavaScript exception. You can obtain the original Java java.lang.Exception object through the javaException property of the JavaScript Error object:

try {

java.lang.System.getProperty(null); // null is not a legal argument


catch(e) { // e is the JavaScript exception

print(e.javaException); // it wraps a java.lang.NullPointerException


One final note about Rhino type conversion is necessary here. Rhino automatically converts primitive numbers and booleans and the nullvalue as needed. Java’s chartype is treated as a JavaScript number, since JavaScript doesn’t have a character type. Java-Script strings are automatically converted to Java strings but (and this can be a stumbling block) Java strings left as java.lang.String objects are not converted back to JavaScript strings. Consider this line of code from earlier:

var version = java.lang.System.getProperty("java.version");

After calling this code, the variable versionholds a java.lang.String object. This usually behaves like a JavaScript string, but there are important differences. First, a Java string has a length() method rather than a length property. Second, the typeof operator returns “object” for a Java string. You can’t convert a Java string to a JavaScript string by calling its toString() method, because all Java objects have their own Java toString() method that returns a java.lang.String. To convert a Java value to a string, pass it to the JavaScript String() function:

var version = String(java.lang.System.getProperty("java.version"));

友情链接It题库(| 版权归yishouce.com所有| 友链等可联系|粤ICP备16001685号-1