2003-04-24 13:14:00 +00:00
|
|
|
|
<html>
|
|
|
|
|
|
|
|
|
|
<head>
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<meta http-equiv=Content-Type content="text/html; charset=utf-8">
|
2003-04-24 13:14:00 +00:00
|
|
|
|
<title>Scripting Java</title>
|
|
|
|
|
</head>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<body>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<h1>Scripting Java</h1>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>This paper shows how to use Rhino to reach beyond JavaScript into
|
|
|
|
|
Java <a href="#ref1">[1]</a>. Scripting Java has many uses. It allows
|
|
|
|
|
us to write powerful scripts quickly by making use of the many Java
|
|
|
|
|
libraries available. We can test Java classes by writing scripts. We
|
|
|
|
|
can also aid our Java development by using scripting for <em>exploratory
|
|
|
|
|
programming</em>. Exploratory programming is the process of
|
|
|
|
|
learning about what a library or API can do by writing quick programs
|
|
|
|
|
that use it. As we will see, scripting makes this process easier.</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Note that the ECMA standard doesn't cover communication with
|
2003-04-24 13:14:00 +00:00
|
|
|
|
Java (or with any external object system for that matter). All the
|
2005-09-20 22:11:54 +00:00
|
|
|
|
functionality covered in this chapter should thus be considered an
|
|
|
|
|
extension.</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<h2>Accessing Java packages and classes</h2>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Every piece of Java code is part of a class. Every Java
|
2003-04-24 13:14:00 +00:00
|
|
|
|
class is part of a package. In JavaScript, however, scripts exist outside of
|
|
|
|
|
any package hierarchy. How then, do we access classes in Java packages?</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Rhino defines a top-level variable named <code>Packages</code>. The
|
|
|
|
|
properties of the <code>Packages</code>
|
|
|
|
|
variable are all the top-level Java packages, such as <code>java</code> and
|
|
|
|
|
<code>com</code>. For example,
|
|
|
|
|
we can access the value of the <code>java</code>package:</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> Packages.java
|
|
|
|
|
[JavaPackage java]
|
|
|
|
|
</pre>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>As a handy shortcut, Rhino defines a top-level variable <code>java</code>
|
|
|
|
|
that is equivalent to <code>Packages.java</code>.
|
2003-04-24 13:14:00 +00:00
|
|
|
|
So the previous example could be even shorter:</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> java
|
|
|
|
|
[JavaPackage java]
|
|
|
|
|
</pre>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>We can access Java classes simply by stepping down the
|
2003-04-24 13:14:00 +00:00
|
|
|
|
package hierarchy:</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> java.io.File
|
|
|
|
|
[JavaClass java.io.File]
|
|
|
|
|
</pre>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>If your scripts access a lot of different Java classes it
|
2003-04-24 13:14:00 +00:00
|
|
|
|
can get awkward to use the full package name of the class every time. Rhino
|
2005-09-20 22:11:54 +00:00
|
|
|
|
provides a top-level function <code>importPackage</code> that serves the same
|
|
|
|
|
purpose as Java's <code>import</code> declaration. For example, we could
|
|
|
|
|
import all of the classes in the <code>java.io</code>package and
|
|
|
|
|
access class <code>java.io.File</code>
|
|
|
|
|
using just the name <code>File</code>:</p>
|
|
|
|
|
<pre>
|
|
|
|
|
js> importPackage(java.io)
|
|
|
|
|
js> File
|
|
|
|
|
[JavaClass java.io.File]
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Here <code>importPackage(java.io)</code> makes all the classes in
|
|
|
|
|
the <code>java.io</code> package<67>(such as <code>File</code>)
|
|
|
|
|
available at the top level. It's equivalent in effect to the Java
|
|
|
|
|
declaration <code>import java.io.*;</code>.</p>
|
|
|
|
|
|
|
|
|
|
<p>It's important to note that Java imports <code>java.lang.*</code>
|
|
|
|
|
implicitly, while Rhino does not. The reason is that JavaScript has
|
|
|
|
|
its own top-level objects <code>Boolean</code>, <code>Math</code>,
|
|
|
|
|
<code>Number</code>, <code>Object</code>, and <code>String</code> that
|
|
|
|
|
are different from the classes by those names defined in the
|
|
|
|
|
<code>java.lang</code> package. Because of this conflict, it's a good
|
|
|
|
|
idea not to use <code>importPackage</code> on the
|
|
|
|
|
<code>java.lang</code> package.</p>
|
|
|
|
|
|
|
|
|
|
<p>One thing to be careful of is Rhino's handling of errors in
|
|
|
|
|
specifying Java package or class names. If <code>java.MyClass</code>
|
|
|
|
|
is accessed, Rhino attempts to load a class named
|
|
|
|
|
<code>java.MyClass</code>. If that load fails, it assumes that
|
|
|
|
|
<code>java.MyClass</code> is a package name, and no error is
|
2003-04-24 13:14:00 +00:00
|
|
|
|
reported:</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> java.MyClass
|
|
|
|
|
[JavaPackage java.MyClass]
|
|
|
|
|
</pre>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Only if you attempt to use this object as a class will an
|
2003-04-24 13:14:00 +00:00
|
|
|
|
error be reported.</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<h2>Working with Java objects</h2>
|
|
|
|
|
|
|
|
|
|
<p>Now that we can access Java classes, the next logical step is to
|
|
|
|
|
create an object. This works just as in Java, with the use of the
|
|
|
|
|
<code>new</code> operator:</p>
|
|
|
|
|
<pre>
|
|
|
|
|
js> new java.util.Date()
|
|
|
|
|
Thu Jan 24 16:18:17 EST 2002
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>If we store the new object in a JavaScript variable, we can then
|
|
|
|
|
call methods on it:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> f = new java.io.File("test.txt")
|
|
|
|
|
test.txt
|
|
|
|
|
js> f.exists()
|
|
|
|
|
true
|
|
|
|
|
js> f.getName()
|
|
|
|
|
test.txt
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Static methods and fields can be accessed from the class object
|
|
|
|
|
itself:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> java.lang.Math.PI
|
|
|
|
|
3.141592653589793
|
|
|
|
|
js> java.lang.Math.cos(0)
|
|
|
|
|
1
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>In JavaScript, unlike Java, the method by itself is an
|
2003-04-24 13:14:00 +00:00
|
|
|
|
object and can be evaluated as well as being called. If we just view the method
|
|
|
|
|
object by itself we can see the various overloaded forms of the method:</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> f.listFiles
|
|
|
|
|
function listFiles() {/*
|
|
|
|
|
java.io.File[] listFiles()
|
|
|
|
|
java.io.File[] listFiles(java.io.FilenameFilter)
|
|
|
|
|
java.io.File[] listFiles(java.io.FileFilter)
|
|
|
|
|
*/}
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>This output shows that the <code>File</code> class defines three
|
|
|
|
|
overloaded methods <code>listFiles</code>: one that takes no
|
|
|
|
|
arguments, another with a <code>FilenameFilter</code> argument, and a
|
|
|
|
|
third with a <code>FileFilter</code> argument. All the methods return
|
|
|
|
|
an array of <code>File</code> objects. Being able to view the
|
|
|
|
|
parameters and return type of Java methods is particularly useful in
|
|
|
|
|
exploratory programming where we might be investigating a method and
|
|
|
|
|
are unsure of the parameter or return types. </p>
|
|
|
|
|
|
|
|
|
|
<p>Another useful feature for exploratory programming is the ability
|
|
|
|
|
to see all the methods and fields defined for an object. Using the
|
|
|
|
|
JavaScript <code>for..in</code> construct, we can print out all these
|
|
|
|
|
values:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> for (i in f) { print(i) }
|
|
|
|
|
exists
|
|
|
|
|
parentFile
|
|
|
|
|
mkdir
|
|
|
|
|
toString
|
|
|
|
|
wait
|
|
|
|
|
<em>[44 others]</em>
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Note that not only the methods of the <code>File</code> class are
|
|
|
|
|
listed, but also the methods inherited from the base class
|
|
|
|
|
<code>java.lang.Object</code> (like <code>wait</code>). This makes it
|
|
|
|
|
easier to work with objects in deeply nested inheritance hierarchies
|
|
|
|
|
since you can see all the methods that are available for that
|
2003-04-24 13:14:00 +00:00
|
|
|
|
object.</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Rhino provides another convenience by allowing properties of
|
|
|
|
|
JavaBeans to be accessed directly by their property names. A JavaBean
|
|
|
|
|
property <code>foo</code> is defined by the methods
|
|
|
|
|
<code>getFoo</code> and <code>setFoo</code>. Additionally, a boolean
|
|
|
|
|
property of the same name can be defined by an <code>isFoo</code>
|
|
|
|
|
method <a href="#ref2">[2]</a>. For example, the following code
|
|
|
|
|
actually calls the <code>File</code> object's <code>getName</code> and
|
|
|
|
|
<code>isDirectory</code> methods.</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> f.name
|
|
|
|
|
test.txt
|
|
|
|
|
js> f.directory
|
|
|
|
|
false
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<h2>Calling overloaded methods</h2>
|
|
|
|
|
|
|
|
|
|
<p>The process of choosing a method to call based upon the types of
|
|
|
|
|
the arguments is called <em>overload resolution</em>. In Java,
|
|
|
|
|
overload resolution is performed at compile time, while in Rhino it
|
|
|
|
|
occurs at runtime. This difference is inevitable given JavaScript's
|
|
|
|
|
use of dynamic typing as was discussed in Chapter 2: since the type of
|
|
|
|
|
a variable is not known until runtime, only then can overload
|
2003-04-24 13:14:00 +00:00
|
|
|
|
resolution occur.</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>As an example, consider the following Java class that defines a
|
|
|
|
|
number of overloaded methods and calls them.</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
public class Overload {
|
|
|
|
|
|
|
|
|
|
public String f(Object o) { return "f(Object)"; }
|
|
|
|
|
public String f(String s) { return "f(String)"; }
|
|
|
|
|
public String f(int i) { return "f(int)"; }
|
|
|
|
|
|
|
|
|
|
public String g(String s, int i) { return "g(String,int)"; }
|
|
|
|
|
public String g(int i, String s) { return "g(int,String)"; }
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
Overload o = new Overload();
|
|
|
|
|
Object[] a = new Object[] { new Integer(3), "hi", Overload.class };
|
|
|
|
|
for (int i = 0; i != a.length; ++i)
|
|
|
|
|
System.out.println(o.f(a[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>When we compile and execute the program, it produces the output</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
f(Object)
|
|
|
|
|
f(Object)
|
|
|
|
|
f(Object)
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>However, if we write a similar script</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
var o = new Packages.Overload();
|
|
|
|
|
var a = [ 3, "hi", Packages.Overload ];
|
|
|
|
|
for (var i = 0; i != a.length; ++i)
|
|
|
|
|
print(o.f(a[i]));
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>and execute it, we get the output</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
f(int)
|
|
|
|
|
f(String)
|
|
|
|
|
f(Object)
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Because Rhino selects an overloaded method at runtime, it calls the
|
|
|
|
|
more specific type that matches the argument. Meanwhile Java selects
|
|
|
|
|
the overloaded method purely on the type of the argument at compile
|
|
|
|
|
time. </p>
|
|
|
|
|
|
|
|
|
|
<p>Although this has the benefit of selecting a method that may be a
|
|
|
|
|
better match for each call, it does have an impact on performance
|
|
|
|
|
since more work is done at each call. In practice this performance
|
|
|
|
|
cost hasn't been noticeable in real applications.</p>
|
|
|
|
|
|
|
|
|
|
<p>Because overload resolution occurs at runtime, it can fail at
|
|
|
|
|
runtime. For example, if we call <code>Overload</code>'s method
|
|
|
|
|
<code>g</code> with two integers we get an error because neither form
|
|
|
|
|
of the method is closer to the argument types than the other:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> o.g(3,4)
|
|
|
|
|
js:"<stdin>", line 2: The choice of Java method Overload.g
|
|
|
|
|
matching JavaScript argument types (number,number) is ambiguous;
|
|
|
|
|
candidate methods are:
|
|
|
|
|
class java.lang.String g(java.lang.String,int)
|
|
|
|
|
class java.lang.String g(int,java.lang.String)
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>A more precise definition of overloading semantics can be
|
|
|
|
|
found at <a
|
|
|
|
|
href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html</a>.</p>
|
|
|
|
|
|
|
|
|
|
<h2>Implementing Java interfaces</h2>
|
|
|
|
|
|
|
|
|
|
<p>Now that we can access Java classes, create Java objects, and
|
|
|
|
|
access fields, methods, and properties of those objects, we have a
|
|
|
|
|
great deal of power at our fingertips. However, there are a few
|
|
|
|
|
instances where that is not enough: many APIs in Java work by
|
|
|
|
|
providing interfaces that clients must implement. One example of this
|
|
|
|
|
is the <code>Thread</code> class: its constructor takes a
|
|
|
|
|
<code>Runnable</code> that contains a single method <code>run</code>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
that will be called when the new thread is started. </p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>To address this need, Rhino provides the ability to create new Java
|
|
|
|
|
objects that implement interfaces. First we must define a JavaScript
|
|
|
|
|
object with function properties whose names match the methods required
|
|
|
|
|
by the Java interface. To implement a <code>Runnable</code>, we need
|
|
|
|
|
only define a single method <code>run</code> with no parameters. If
|
|
|
|
|
you remember from Chapter 3, it is possible to define a JavaScript
|
|
|
|
|
object with the <code>{propertyName: value}</code> notation. We can
|
|
|
|
|
use that syntax here in combination with a function expression to
|
|
|
|
|
define a JavaScript object with a <code>run</code> method:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> obj = { run: function () { print("\nrunning"); } }
|
|
|
|
|
[object Object]
|
|
|
|
|
js> obj.run()
|
|
|
|
|
|
|
|
|
|
running
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Now we can create an object implementing the <code>Runnable</code> interface
|
|
|
|
|
by constructing a <code>Runnable</code>:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> r = new java.lang.Runnable(obj);
|
|
|
|
|
[object JavaObject]
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>In Java it is not possible to use the <code>new</code> operator on
|
|
|
|
|
an interface because there is no implementation available. Here Rhino
|
|
|
|
|
gets the implementation from the JavaScript object
|
|
|
|
|
<code>obj</code>. Now that we have an object implementing
|
|
|
|
|
<code>Runnable</code>, we can create a <code>Thread</code> and run
|
|
|
|
|
it. The function we defined for <code>run </code>will be called on a
|
|
|
|
|
new thread.</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> t = new java.lang.Thread(r)
|
|
|
|
|
Thread[Thread-2,5,main]
|
|
|
|
|
js> t.start()
|
|
|
|
|
js>
|
|
|
|
|
|
|
|
|
|
running
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>The final <code>js</code> prompt and the output from the new thread
|
|
|
|
|
may appear in either order, depending on thread scheduling.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<p>Behind the scenes, Rhino generates the bytecode for a new Java
|
|
|
|
|
class that implements <code>Runnable</code> and forwards all calls to
|
|
|
|
|
its <code>run</code> method over to an associated JavaScript
|
|
|
|
|
object. The object that implements this class is called a <em>Java
|
|
|
|
|
adapter</em>. Because the forwarding to JavaScript occurs at runtime,
|
|
|
|
|
it is possible to delay defining the methods implementing an interface
|
|
|
|
|
until they are called. While omitting a required method is bad
|
|
|
|
|
practice for programming in the large, it's useful for small scripts
|
|
|
|
|
and for exploratory programming.</p>
|
|
|
|
|
|
|
|
|
|
<h2>The <code>JavaAdapter</code> constructor</h2>
|
|
|
|
|
|
|
|
|
|
<p>In the previous section we created Java adapters using the
|
|
|
|
|
<code>new</code> operator with Java interfaces. This approach has its
|
|
|
|
|
limitations: it's not possible to implement multiple interfaces, nor
|
|
|
|
|
can we extend non-abstract classes. For these reasons there is a
|
|
|
|
|
<code>JavaAdapter</code> constructor. </p>
|
|
|
|
|
|
|
|
|
|
<p>The syntax of the <code>JavaAdapter</code> constructor is</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
new JavaAdapter(javaIntfOrClass, [javaIntf, ..., javaIntf,] javascriptObject)
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Here <code>javaIntfOrClass</code> is an interface to implement or a
|
|
|
|
|
class to extend and <code>javaIntf</code> are aditional interfaces to
|
|
|
|
|
implement. The <code>javascriptObject</code> is the JavaScript object
|
|
|
|
|
containing the methods that will be called from the Java adapter. </p>
|
|
|
|
|
|
|
|
|
|
<p>In practice there's little need to call the
|
|
|
|
|
<code>JavaAdapter</code> constructor directly. Most of the time the
|
|
|
|
|
previous syntaxes using the <code>new</code> operator will be
|
|
|
|
|
sufficient.</p>
|
|
|
|
|
|
|
|
|
|
<h2>JavaScript functions as Java interfaces</h2>
|
|
|
|
|
|
|
|
|
|
<p>Often we need to implement an interface with only one method, like in the
|
|
|
|
|
previous <code>Runnable</code> example or when providing various event
|
|
|
|
|
listener implementations. To facilitate this Rhino allows to pass
|
|
|
|
|
JavaScript function when such interface is expected. The
|
|
|
|
|
function is called as the implementation of interface method.</p>
|
|
|
|
|
|
|
|
|
|
<p>Here is the simplified <code>Runnable</code> example:</p>
|
|
|
|
|
<pre>
|
|
|
|
|
js> t = java.lang.Thread(function () { print("\nrunning"); });
|
|
|
|
|
Thread[Thread-0,5,main]
|
|
|
|
|
js> t.start()
|
|
|
|
|
js>
|
|
|
|
|
running
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
Rhino also allows to use JavaScript function as implementation of Java
|
|
|
|
|
interface with more then method if all the methods has the same
|
|
|
|
|
signature. When calling the function, Rhino passes method's name as
|
|
|
|
|
the additional argument. Function can
|
|
|
|
|
use it to distinguish on behalf of which method it was called:
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> var frame = new Packages.javax.swing.JFrame();
|
|
|
|
|
js> frame.addWindowListener(function(event, methodName) {
|
|
|
|
|
if (methodName == "windowClosing") {
|
|
|
|
|
print("Calling System.exit()..."); java.lang.System.exit(0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
js> frame.setSize(100, 100);
|
|
|
|
|
js> frame.visible = true;
|
|
|
|
|
true
|
|
|
|
|
js> Calling System.exit()...
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<h2>Creating Java arrays</h2>
|
|
|
|
|
|
|
|
|
|
<p>Rhino provides no special syntax for creating Java arrays. You
|
|
|
|
|
must use the <code>java.lang.reflect.Array</code> class for this
|
|
|
|
|
purpose. To create an array of five Java strings you would make the
|
|
|
|
|
following call:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> a = java.lang.reflect.Array.newInstance(java.lang.String, 5);
|
|
|
|
|
[Ljava.lang.String;@7ffe01
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>To create an array of primitive types, we must use the special TYPE
|
|
|
|
|
field defined in the associated object class in the
|
|
|
|
|
<code>java.lang</code> package. For example, to create an array of
|
|
|
|
|
bytes, we must use the special field
|
|
|
|
|
<code>java.lang.Byte.TYPE</code>:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> a = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 2);
|
|
|
|
|
[C@7a84e4
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>The resulting value can then be used anywhere a Java array
|
2003-04-24 13:14:00 +00:00
|
|
|
|
of that type is allowed.</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> a[0] = 104
|
|
|
|
|
104
|
|
|
|
|
js> a[1] = 105
|
|
|
|
|
105
|
|
|
|
|
js> new java.lang.String(a)
|
|
|
|
|
hi
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<h2>Java strings and JavaScript strings</h2>
|
|
|
|
|
|
|
|
|
|
<p>It's important to keep in mind that Java strings and JavaScript
|
|
|
|
|
strings are <strong>not</strong> the same. Java strings are instances
|
|
|
|
|
of the type <code>java.lang.String</code> and have all the methods
|
|
|
|
|
defined by that class. JavaScript strings have methods defined by
|
|
|
|
|
<code>String.prototype</code>. The most common stumbling block is
|
|
|
|
|
<code>length</code>, which is a method of Java strings and a dynamic
|
|
|
|
|
property of JavaScript strings:</p>
|
|
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
|
js> javaString = new java.lang.String("Java")
|
|
|
|
|
Java
|
|
|
|
|
js> jsString = "JavaScript"
|
|
|
|
|
JavaScript
|
|
|
|
|
js> javaString.length()
|
|
|
|
|
4
|
|
|
|
|
js> jsString.length
|
|
|
|
|
10
|
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
<p>Rhino provides some help in reducing the differences between the
|
|
|
|
|
two types. First, you can pass a JavaScript string to a Java method
|
|
|
|
|
that requires a Java string and Rhino will perform the conversion. We
|
|
|
|
|
actually saw this feature in action on the call to the
|
|
|
|
|
<code>java.lang.String</code> constructor in the preceding
|
2003-04-24 13:14:00 +00:00
|
|
|
|
example.</p>
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p>Rhino also makes the JavaScript methods available to Java strings
|
|
|
|
|
if the java.lang.String class doesn't already define them. For
|
|
|
|
|
example:</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<pre>
|
|
|
|
|
js> javaString.match(/a.*/)
|
|
|
|
|
ava
|
|
|
|
|
</pre>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
|
|
|
|
<hr align=left size=1 width="33%">
|
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p><a name="ref1">[1]</a>
|
|
|
|
|
The ability to call Java from JavaScript was first implemented as part
|
|
|
|
|
of a Netscape browser technology called
|
|
|
|
|
<em>LiveConnect</em>. However, since that technology also
|
|
|
|
|
encompassed communication with browser plugins, and since the way of
|
|
|
|
|
calling JavaScript from Java in Rhino is entirely different, that term
|
|
|
|
|
won't be used in this paper.</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
2005-09-20 22:11:54 +00:00
|
|
|
|
<p><a name="ref2">[2]</a>
|
|
|
|
|
For more information on JavaBeans, see <em>Developing Java Beans</em>
|
|
|
|
|
by Robert Englander.</p>
|
2003-04-24 13:14:00 +00:00
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|