aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/zh-cn/mozilla/projects/rhino/scripting_java/index.html')
-rw-r--r--files/zh-cn/mozilla/projects/rhino/scripting_java/index.html397
1 files changed, 0 insertions, 397 deletions
diff --git a/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html b/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html
deleted file mode 100644
index 013ad3aa89..0000000000
--- a/files/zh-cn/mozilla/projects/rhino/scripting_java/index.html
+++ /dev/null
@@ -1,397 +0,0 @@
----
-title: Scripting Java
-slug: Mozilla/Projects/Rhino/Scripting_Java
-translation_of: Mozilla/Projects/Rhino/Scripting_Java
----
-<p>这篇文章描述了如何在rhino中使用java。使用脚本调用Java有很多用途,它使得我们可以利用Java中现有的库,来帮助我们构建强大的脚本。我们可以通过编写脚本,来对Java程序进行测试。可以通过脚本来进行探索式编程,辅助Java的开发,所谓探索式编程,就是通过快速地编程调用库或API来探索这些库或API可以做什么,显而易见,脚本语言很适合探索式编程。</p>
-
-<p>这里注意,ECMA标准并没有包含和Java(或者其他任何对象系统)交互的标准。本文所描述的所有内容,应该被认为是一个扩展。</p>
-
-
-
-<h3 id="访问_Java_Packages_和_Classes">访问 Java Packages 和 Classes</h3>
-
-<p>Java的每段代码都是类的一部分,每一个JAVA类都是包的一部分。在Javascript中,脚本不属于任何package。我们可以访问Java包中的类么?</p>
-
-<p>Rhino定义了一个顶层的变量Packages。Packages的所有属性都是Java中顶层的包,比如java和com。比如我们可以访问java包:</p>
-
-<pre class="code">js&gt; Packages.java
-[JavaPackage java]</pre>
-
-<p>还有一种更方便的方式,Rhino定义了一个顶层的变量java,等价于Packages.java。所以上面的例子可以更简介地写成:</p>
-
-<pre class="code">js&gt; java
-[JavaPackage java]
-</pre>
-
-<p>我们可以通过访问包的下层,来直接访问java类:</p>
-
-<pre class="code">js&gt; java.io.File
-[JavaClass java.io.File]
-</pre>
-
-<p>如果你的脚本需要访问很多的Java类,每次都附带完整的包名会使得编程很麻烦。Rhino提供了一个顶层的方法importPackage,它的功能和Java的import一样。比如,我们可以导入java.io包中的所有类,然后直接通过类名File来访问java.io.File:</p>
-
-<pre class="code">js&gt; importPackage(java.io)
-js&gt; File
-[JavaClass java.io.File]
-</pre>
-
-<p>这里importPackage(java.io)使得java.io包中的所有类(例如File)可以在顶层被访问。这和Java中的java.io.*;等价。</p>
-
-<p>要注意Java会暗中导入java.lang.*,但是Rhino不会。因为JavaScript的顶层对象Boolean、Math、Number、Object和String和java.lang包中同名的类并不相同。因为这种冲突,建议不要用importPackage来导入java.lang包。</p>
-
-<p>有一点要注意的,就是Rhino对于指定包名或类名时是如何处理错误的。如果java.Myclass是可访问的,Rhino会试图加载名为java.MyClass的类,如果加载失败,它会假设java.MyClass是一个包名,不会报错:</p>
-
-<pre class="code">js&gt; java.MyClass
-[JavaPackage java.MyClass]
-</pre>
-
-<p>只有在你试图将这个对象当作类使用时,才会报错。</p>
-
-<h4 id="额外的包和类">额外的包和类</h4>
-
-<p>额外的包和类也可以在Rhino中使用。确认你的.jar或.class文件在你的classpath里,你就可以在你的JavaScript应用中导入它们。这些包基本不会在java包中,所以你在使用时,需要在包前加上前缀"Packages"。 比如你想导入 <code>org.mozilla.javascript</code> 包,你应该像下面这样去使用importPackage():</p>
-
-<pre class="code">$ java org.mozilla.javascript.tools.shell.Main
-js&gt; importPackage(Packages.org.mozilla.javascript);
-js&gt; Context.currentContext;
-org.mozilla.javascript.Context@bb6ab6
-</pre>
-
-<p>偶尔,我们也会见到在一些例子中使用包的完整名称,而没有使用importPackage()。这也是可以的,只是会让你多打一些字。如果使用完整的名称,上面的例子就会变成下面这样:</p>
-
-<pre class="code">$ java org.mozilla.javascript.tools.shell.Main
-js&gt; jsPackage = Packages.org.mozilla.javascript;
-[JavaPackage org.mozilla.javascript]
-js&gt; jsPackage.Context.currentContext;
-org.mozilla.javascript.Context@bb6ab6
-</pre>
-
-<p>同样,你可以通过importClass()来导入一个类,上面的例子也可以像这样写:</p>
-
-<pre>$ java org.mozilla.javascript.tools.shell.Main
-js&gt; importClass(Packages.org.mozilla.javascript.Context);
-js&gt; Context.currentContext;
-org.mozilla.javascript.Context@bb6ab6</pre>
-
-<h3 id="和Java一起工作">和Java一起工作</h3>
-
-<p>现在我们可以访问Java类,下一步就是要创建一个对象。方法就和在Java中一样, 用new来创建对象:</p>
-
-<pre class="code">js&gt; new java.util.Date()
-Thu Jan 24 16:18:17 EST 2002
-</pre>
-
-<p>如果我们将创建的对象存放在JavaScript变量中,我们可以调用它的方法:</p>
-
-<pre class="code">js&gt; f = new java.io.File("test.txt")
-test.txt
-js&gt; f.exists()
-true
-js&gt; f.getName()
-test.txt
-</pre>
-
-<p>静态方法和属性可以直接通过类对象来访问:</p>
-
-<pre class="code">js&gt; java.lang.Math.PI
-3.141592653589793
-js&gt; java.lang.Math.cos(0)
-1
-</pre>
-
-<p>不像Java,在JavaScript里,方法就是一个对象。它可以被评估,也可以被调用。如果我们去查看这个方法,我们可以看到这个方法所有重载的形式:</p>
-
-<pre class="code">js&gt; f.listFiles
-function listFiles() {/*
-java.io.File[] listFiles()
-java.io.File[] listFiles(java.io.FilenameFilter)
-java.io.File[] listFiles(java.io.FileFilter)
-*/}
-</pre>
-
-<p>输出告诉我们,File类有listFiles方法的三种重载:一种不包含参数的,另一种包含一个FilenameFilter类型的参数,第三个包含一个FileFilter类型的参数。所有的方法都返回一个File对象数组。可以观察到Java方法的参数和返回类型在探索式编程中是非常有用的,尤其是在对一个方法的参数和返回对象不确定的时候。</p>
-
-<p>另一个有助于探索式编程的特性,是可以看到对象中定义的所有方法和属性。用JavaScript的<code>for..in</code> , 我们可以打印这些值:</p>
-
-<pre class="code">js&gt; for (i in f) { print(i) }
-exists
-parentFile
-mkdir
-toString
-wait
-<em>[44 others]</em>
-</pre>
-
-<p>注意这里不仅列出了File类中的所有方法,也列出了从基类java.lang.Object中继承的方法,例如wait。这使得我们可以更好地处理那些有复杂继承关系的对象,因为我们可以看到对象中所有可用的方法。</p>
-
-<p>Rhino可以通过属性名来方便地访问JavaBean的属性。一个JavaBean的属性foo被方法getFoo和setFoo定义,另外,一个也叫foo的boolean类型的属性,可以被isFoo来定义。比如, 下面的代码实际上调用了File对象的getName和isDirectory方法。</p>
-
-<pre class="code">js&gt; f.name
-test.txt
-js&gt; f.directory
-false
-</pre>
-
-<h3 id="调用重载方法"><font><font>调用重载方法</font></font></h3>
-
-<p> <span id="noHighlight_0.8335956993210636">根据参数类型选择调用方法的过程称为重载决议。在 Java 中, 重载决议在编译时执行, 而在rhino中则在运行时发生。这种差异是不可避免的, 因为 JavaScript 使用动态类型, 在2章中: 由于变量的类型直到运行时才知道, 才会发生重载决议。</span></p>
-
-<div class="textArea" id="destText" style="direction: ltr;">
-<div><span id="noHighlight_0.37802431709856343">例如, 请查看下面的 Java 类, 它定义了许多重载方法并调用它们。</span> </div>
-</div>
-
-
-
-<pre class="code">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><span id="noHighlight_0.42609135329922554">当我们编译和执行程序, 它产生输出</span></p>
-
-<pre class="code">f(Object)
-f(Object)
-f(Object)
-</pre>
-
-<p><span id="noHighlight_0.9335258512242988">但是, 如果我们编写一个类似的脚本</span></p>
-
-<pre class="code">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>并且运行它,将会输出</p>
-
-<pre class="code">f(int)
-f(String)
-f(Object)
-</pre>
-
-<p>因为Rhino在运行时选择重载方法, <span id="noHighlight_0.45030814581159195">所以它会调用与该参数匹配的更具体的类型。</span> <span id="noHighlight_0.45030814581159195">同时, 在编译时, Java 只在参数的类型上选择重载方法。</span></p>
-
-<p>尽管这有利于选择一种方法,这种方法可能是每个调用的更好匹配,但它确实对性能有影响,因为每次调用时都要做更多的工作。事实上,这种性能代价在实际应用中并不明显。</p>
-
-<p>因为重载决议发生在运行时,它可能在运行时失败。例如,如果我们用两个整数调用重载方法g,我们就会得到一个错误,因为方法的两个形式都比另一个更接近参数类型:</p>
-
-<pre class="code">js&gt; o.g(3,4)
-js:"&lt;stdin&gt;", 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 href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html</a> 提供了<font><font>一个更精确的重载语义定义</font><font>。</font></font></p>
-
-<h3 id="实现Java接口">  实现Java接口</h3>
-
-
-
-<p>现在我们可以访问Java类,创建Java对象,并访问这些对象的字段、方法和属性,我们就可以轻松掌握大量的功能。但是,在少数情况下是不够用的:Java中的很多API通过提供客户端必须实现的接口来工作。其中一个例子就是<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">Thread</span></font>类:其构造函数Runnable包含一个<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">run</span></font>方法,这个方法在新线程启动时被调用。</p>
-
-<p>为了满足这种需求,Rhino提供了创建新的Java对象实现的接口的能力。首先,我们必须定义一个JavaScript对象,其中的函数属性的名称与Java接口所需的方法名称相匹配。要实现一个<code>Runnable</code> ,我们只需要定义一个不带参数的<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">run</span></font>单方法。如果你还记得第3章,可以用{ propertyName: value}符号定义一个JavaScript对象。我们可以在这里结合函数表达式使用这个语法来用一个 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">run</span></font>方法定义一个JavaScript对象:</p>
-
-<pre class="code">js&gt; obj = { run: function () { print("\nrunning"); } }
-[object Object]
-js&gt; obj.run()
-
-running
-</pre>
-
-
-
-<p>现在我们可以通过构建一个 <code>Runnable</code> 来实现 <code>Runnable</code> 接口的对象:</p>
-
-<pre><code>js&gt; r = new java.lang.Runnable(obj);</code></pre>
-
-
-
-<pre class="code">js&gt; r = new java.lang.Runnable(obj);
-[object JavaObject]
-</pre>
-
-<p><font><font>在Java中,不可能</font></font><font><font>在接口上</font><font>使用</font></font><code>new</code><font><font>运算符,因为没有可用的实现。</font><font>Rhino从JavaScript对象中获取实现</font></font><code>obj</code><font><font>。</font><font>现在我们有一个对象实现</font></font><code>Runnable</code><font><font>,我们可以创建</font></font><code>Thread</code><font><font>并运行它。</font><font>我们定义的函数</font></font><code>run </code><font><font>将在新线程上调用。</font></font></p>
-
-<pre class="code">js&gt; t = new java.lang.Thread(r)
-Thread[Thread-2,5,main]
-js&gt; t.start()
-js&gt;
-
-running
-</pre>
-
-
-
-<p><font><font>最终</font></font><code>js</code><font><font>提示和新线程的输出可能以任意顺序显示,具体取决于线程调度。</font></font></p>
-
-<p>在后台,Rhino为一个新的Java类生成字节码,该类实现 <code>Runnable</code> 并转发对其 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.498039);">run</span></font>方法的所有调用,并转发给关联的JavaScript对象。实现此类的对象称为Java适配器。因为转发到JavaScript是在运行时发生的,所以可能会延迟定义实现接口的方法直到它们被调用。虽然省略必要的方法对大编程来说是一种糟糕的做法,但它对小脚本和探索性编程很有用。</p>
-
-
-
-<h3 id="JavaAdapter构造函数"><font><font>JavaAdapter构造函数</font></font></h3>
-
-<p>在前面的章节中,我们使用 <code>new</code> 运算符与Java接口创建Java适配器。这种方法有其局限性:不可能实现多个接口,也不能扩展非抽象类。因为这些<font><font>原因,有一个</font></font> <code>JavaAdapter</code> 构造函数。</p>
-
-<p><code>JavaAdapter</code><font><font>构造函数</font><font>的语法</font><font>是:</font></font></p>
-
-<pre class="code">new JavaAdapter(javaIntfOrClass, [javaIntf, ..., javaIntf,] javascriptObject)
-</pre>
-
-<p><code><font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">这里</span></font>javaIntfOrClass</code>是一个实现的接口或一个扩展的类,并且<code>javaIntf</code>是实现接口的接口。而<code>javascriptObject</code> 则包含从Java适配器调用的方法的JavaScript对象。</p>
-
-<p>在实践中,几乎不需要<code>JavaAdapter</code> 直接调用构造函数。大多数情况下,使用<code>new</code>运算符之前的语法就足够了。</p>
-
-<h3 id="作为Java接口的JavaScript函数"><font><font>作为Java接口的JavaScript函数</font></font></h3>
-
-<p>通常我们只需要使用一种方法实现一个接口,<font><font>就像前面的</font></font> <code>Runnable</code> <font><font>例子或者提供各种事件监听器实现一样。</font>为了方便这个,Rhino允许在这种接口传递JavaScript函数。</font><font>该函数被称为接口方法的实现。</font></p>
-
-<p>这里是简化的 <code>Runnable</code> 实例:</p>
-
-<pre class="code">js&gt; t = java.lang.Thread(function () { print("\nrunning"); });
-Thread[Thread-0,5,main]
-js&gt; t.start()
-js&gt;
-running
-</pre>
-
-<p><font>如果所有的方法都具有相同的签名,Rhino还允许使用JavaScript函数作为Java接口的实现方法。当调用函数时,Rhino将方法的名称作为附加参数传递。函数可以使用它</font>来代表被调用<font>的方法:</font></p>
-
-<pre class="code">js&gt; var frame = new Packages.javax.swing.JFrame();
-js&gt; frame.addWindowListener(function(event, methodName) {
- if (methodName == "windowClosing") {
- print("Calling System.exit()..."); java.lang.System.exit(0);
- }
- });
-js&gt; frame.setSize(100, 100);
-js&gt; frame.visible = true;
-true
-js&gt; Calling System.exit()...
-</pre>
-
-<h3 id="创建Java数组"><font><font>创建Java数组</font></font></h3>
-
-<p>Rhino不提供创建Java数组的特殊语法。你必须使用这个 <code>java.lang.reflect.Array</code> 类来达到这个目的。要创建一个由五个Java字符串组成的数组,可以进行以下调用:</p>
-
-<pre class="code">js&gt; a = java.lang.reflect.Array.newInstance(java.lang.String, 5);
-[Ljava.lang.String;@7ffe01
-</pre>
-
-<p>要创建一个基本类型数组,我们必须使用 <code>java.lang</code> 包中相关对象类中定义的特殊TYPE字段。例如,要创建一个字节数组,我们必须使用特殊字段 <code>java.lang.Byte.TYPE</code>:</p>
-
-<pre class="code">js&gt; a = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 2);
-[C@7a84e4
-</pre>
-
-<p>而且结果值是允许被使用在该类型的Java数组的任何地方。</p>
-
-<pre class="code">js&gt; a[0] = 104
-104
-js&gt; a[1] = 105
-105
-js&gt; new java.lang.String(a)
-hi
-</pre>
-
-<h3 id="Java字符串和JavaScript字符串"><font><font>Java字符串和JavaScript字符串</font></font></h3>
-
-<p><font><font>请记住,Java字符串和JavaScript字符串是</font></font><strong><font><font>不</font></font></strong><font><font>一样的。</font><font>Java字符串类型的实例,</font></font><code>java.lang.String</code> ,<font><font>并具有由该类定义的所有方法。</font><font>JavaScript字符串具有由...定义的方法,</font></font><code>String.prototype</code>. <font><font>最常见的绊脚石是</font></font> <code>length</code>, <font><font><font face="consolas, Liberation Mono, courier, monospace">这是Java</font>字符串方法和JavaScript字符串的动态属性:</font></font></p>
-
-<pre class="code">js&gt; javaString = new java.lang.String("Java")
-Java
-js&gt; jsString = "JavaScript"
-JavaScript
-js&gt; javaString.length()
-4
-js&gt; jsString.length
-10
-</pre>
-
-<p>Rhino <font>在减少这两种类型之间的差异方面提供了一些帮助。</font><font>首先,您可以将JavaScript字符串传递给需要Java字符串的Java方法,Rhino将执行转换。</font><font>实际上,我们在前面</font><code>java.lang.String</code> <font>例子中</font><font>的</font><font>构造函数</font><font>调用中看到了这个特性</font><font>。</font></p>
-
-<p><font>如果</font><code>java.lang.String</code> <font>类尚未定义它们,Rhino还会使JavaScript方法可用于Java字符串。例如:</font></p>
-
-<pre class="code">js&gt; javaString.match(/a.*/)
-ava
-</pre>
-
-<h3 id="JavaImporter_构造函数">JavaImporter 构造函数</h3>
-
-<p><code>JavaImporter</code>是一个新的全局构造函数,它允许在脚本化Java时省略显式的包名称:</p>
-
-<pre>var SwingGui = JavaImporter(Packages.javax.swing,
- Packages.javax.swing.event,
- Packages.javax.swing.border,
- java.awt.event,
- java.awt.Point,
- java.awt.Rectangle,
- java.awt.Dimension);
-...
-
-with (SwingGui) {
- var mybutton = new JButton(test);
- var mypoint = new Point(10, 10);
- var myframe = new JFrame();
-...
-}
-</pre>
-
-<p>以前,这样的功能仅适用于将 <code>org.mozilla.javascript.ImporterTopLevel</code> 用作顶级作用域的嵌入。这个类提供额外的 <code>importPackage()</code> 和<code>importClass()</code> 全局函数的脚本,但其广泛的使用有污染Java类名的全局命名空间的趋势,还有防止垃圾收集加载类。</p>
-
-<p>详情请参阅 <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=245882">Bugzilla 245882</a>.</p>
-
-<h3 id="Java_异常">Java 异常</h3>
-
-
-
-<p><font><font>JavaScript代码使用</font></font> <code>try ... catch</code> 语句<font><font>可以捕获Java方法抛出的异常</font><font>。</font><font>Rhino将Java异常封装到具有以下属性的错误对象中:</font></font></p>
-
-<ul>
- <li><code>javaException</code><font><font>:Java方法抛出的原始异常</font></font></li>
- <li><code>rhinoException</code><font><font>:由Rhino运行时包装的异常</font></font></li>
-</ul>
-
-<p><code>instanceof</code><font><font>运算符可用于查询异常的类型:</font></font></p>
-
-
-
-<pre>try {
- java.lang.Class.forName("NonExistingClass");
-} catch (e) {
- if (e.javaException instanceof java.lang.ClassNotFoundException) {
- print("Class not found");
- }
-}
-</pre>
-
-<p>Rhino 还支持对 <code>try... catch</code> 语句的扩展,允许定义条件捕获异常:</p>
-
-<pre>function classForName(name) {
- try {
- return java.lang.Class.forName(name);
- } catch (e if e.javaException instanceof java.lang.ClassNotFoundException) {
- print("Class " + name + " not found");
- } catch (e if e.javaException instanceof java.lang.NullPointerException) {
- print("Class name is null");
- }
-}
-
-classForName("NonExistingClass");
-classForName(null);
-</pre>