`
- 浏览:
16737 次
- 性别:
- 来自:
深圳
-
Java 6 中也可以运行 javascript 喽 (转)
- 给 Java SE 注入脚本语言的活力
- Mustang 的脚本语言新特性
-
- 文档选项
-
- 将此页作为电子邮件发送
-
- 将此页作为电子邮件发送
-
-
-
-
-
- 级别: 中级
-
- 吴 玥颢 (wuyuehao@cn.ibm.com), 软件工程师, IBM
-
-
- 2006 年 10 月 30 日
-
- 在即将发布的 Java SE6(Mustang)中,增加了对脚本语言的支持。通过对脚本语言的调用,使得一些通常用 Java 比较难于实现的功能变得简单和轻便。脚本语言与 Java 之间的互操作将变得优雅而直接。
-
- 脚本语言与 Java
-
- 假设我们有一个简单的需求,察看一份文档中 5 个字母组成的单词的个数。用 Java 一般实现如下:
-
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.io.IOException;
-
- public class Find5Words {
- public static void main(String[] args) throws IOException {
- String result = "";
- String line = null;
- int num = 0;
- FileReader fr = new FileReader("filename");
- BufferedReader br = new BufferedReader(fr);
- while ((line = br.readLine()) != null) {
- result += line;
- }
- br.close();
- fr.close();
- String[] s = result.split(" ");
- for (int i = 0; i < s.length; i++) {
- if (s[i].matches("^//w{5}$")) {
- num++;
- }
- }
- System.out.println(num);
- }
- }
-
-
-
-
- 再看看 Perl 语言实现同样功能的代码:
-
- open FILE, "<filename ";
- while (<FILE>) {
- for (split) {
- $num++ if /^/w{5}$/
- }
- }
- print $num;
-
-
-
-
- 那么有没有一种优雅的方式将 Java 与脚本语言结合呢,在今年秋季即将发布的 Java SE6(代号 Mustang)中,这将成为现实。
-
-
-
-
-
-
- 回页首
-
-
-
-
- Mustang 的脚本引擎
-
- JSR 233 为 Java 设 计了一套脚本语言 API。这一套 API 提供了在 Java 程序中调用各种脚本语言引擎的接口。任何实现了这一接口的脚本语言引擎都可以 在 Java 程序中被调用。在 Mustang 的发行版本中包括了一个基于 Mozilla Rhino 的 JavaScript 脚本引擎。
-
- Mozilla Rhino
-
- Rhino 是一个纯 Java 的开源的 JavaScript 实现。他的名字来源于 O'Reilly 关于 JavaScript 的书的封面:
-
-
- Rhino 项 目可以追朔到 1997 年,当时 Netscape 计划开发一个纯 Java 实现的 Navigator,为此需要一个 Java 实现 的 JavaScript —— Javagator。它也就是 Rhino 的前身。起初 Rhino 将 JavaScript 编译 成 Java 的二进制代码执行,这样它会有最好的性能。后来由于编译执行的方式存在垃圾收集的问题并且编译和装载过程的开销过大,不能满足一些项目的需 求,Rhino 提供了解释执行的方式。随着 Rhino 开放源代码,越来越多的用户在自己的产品中使用了 Rhino,同时也有越来越多的开发者参与 了 Rhino 的开发并做出了很大的贡献。如今 Rhino1.6R2 版本将被包含在 Java SE6 中发行,更多的 Java 开发者将从中获 益。
-
- Rhino 提供了如下功能
-
- 对 JavaScript 1.5 的完全支持
- 直接在 Java 中使用 JavaScript 的功能
- 一个 JavaScript shell 用于运行 JavaScript 脚本
- 一个 JavaScript 的编译器,用于将 JavaScript 编译成 Java 二进制文件
- 支持的脚本语言
-
- 在 dev.java.net可以找到官方的脚本引擎的实现项目。这一项目基于BSD License ,表示这些脚本引擎的使用将十分自由。目前该项目已对 包括 Groovy, JavaScript, Python, Ruby, PHP 在内的二十多种脚本语言提供了支持。这一支持列表还将不断扩 大。
-
- 在 Mustang 中对脚本引擎的检索使用了工厂模式。首先需要实例化一个工厂 —— ScriptEngineManager。
-
-
- ScriptEngineManager factory = new ScriptEngineManager();
-
-
-
-
- ScriptEngineManager 将在 Thread Context ClassLoader 的 Classpath 中根据 jar 文件的 META-INF 来查找可用的脚本引擎。它提供了 3 种方法来检索脚本引擎:
-
-
- ScriptEngine engine = factory.getEngineByName ("JavaScript");
-
- ScriptEngine engine = factory.getEngineByExtension ("js");
-
- ScriptEngine engine = factory.getEngineByMimeType ("application/javascript");
-
-
-
-
- 下面的代码将会打印出当前的 JDK 所支持的所有脚本引擎
-
- ScriptEngineManager factory = new ScriptEngineManager();
- for (ScriptEngineFactory available : factory.getEngineFactories()) {
- System.out.println(available.getEngineName());
- }
-
-
-
-
- 以下各章节代码将以 JavaScript 为例。
-
- 在 Java 中解释脚本
-
- 有了脚本引擎实例就可以很方便的执行脚本语言,按照惯例,我们还是从一个简单的 Hello World 开始:
-
- public class RunJavaScript {
- public static void main(String[] args){
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName ("JavaScript");
- engine.eval("print('Hello World')");
- }
- }
-
-
-
-
- 这段 Java 代码将会执行 JavaScript 并打印出 Hello World。如果 JavaScript 有语法错误将会如何?
-
- engine.eval("if(true){println ('hello')");
-
-
-
- 故意没有加上”}”,执行这段代码 Java 将会抛出一个 javax.script.ScriptException 并准确的打印出错信息: Exception in thread "main" javax.script.ScriptException:
- sun.org.mozilla.javascript.internal.EvaluatorException:
- missing } in compound statement (<Unknown source>#1) in <Unknown source>
- at line number 1
- at ...
-
-
-
-
- 如果我们要解释一些更复杂的脚本语言,或者想在运行时改变该脚本该如何做呢?脚本引擎支持一个重载的 eval 方法,它可以从一个 Reader 读入所需的脚本:
-
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName ("JavaScript");
- engine.eval(new Reader("HelloWorld.js"));
-
-
-
- 如此这段 Java 代码将在运行时动态的寻找 HelloWorld.js 并执行,用户可以随时通过改变这一脚本文件来改变 Java 代码的行为。做一个简单的实验,Java 代码如下: public class RunJavaScript {
- public static void main(String[] args) throws FileNotFoundException,
- ScriptException, InterruptedException {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName ("JavaScript");
- while (true) {
- engine.eval(new FileReader("HelloWorld.js"));
- Thread.sleep(1000);
- }
- }
- }
-
-
-
-
- HelloWorld.js 内容为简单的打印一个 Hello World: print('Hello World');
-
- 运行 RunJavaScript 将会每一秒钟打印一个 Hello World。这时候修改 HelloWorld.js 内容为 print('Hello Tony');
-
- 打 印的内容将变为 Hello Tony,由此可见 Java 程序将动态的去读取脚本文件并解释执行。对于这一简单的 Hello World 脚本来 说,IO 操作将比直接执行脚本损失 20% 左右的性能(在我的 Think Pad 上),但他带来的灵活性——在运行时动态改变代码的能力,在某些 场合是十分激动人心的。
-
- 脚本语言与 Java 的通信
-
- ScriptEngine 的 put 方法用于将一个 Java 对象映射成一个脚本语言的变量。现在有一个 Java Class,它只有一个方法,功能就是打印一个字符串 Hello World:
-
- package tony;
-
- public class HelloWorld {
- String s = "Hello World";
- public void sayHello(){
- System.out.println(s);
- }
- }
-
-
-
-
- 那么如何在脚本语言中使用这个类呢?put 方法可以做到:
-
- import javax.script.ScriptEngine;
- import javax.script.ScriptEngineManager;
- import javax.script.ScriptException;
-
- public class TestPut {
- public static void main(String[] args) throws ScriptException {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("JavaScript");
- HelloWorld hello = new HelloWorld();
- engine.put("script_hello", hello);
- engine.eval("script_hello.sayHello()");
- }
- }
-
-
-
-
- 首 先我们实例化一个 HelloWorld,然后用 put 方法将这个实例映射为脚本语言的变量 script_hello。那么我们就可以 在 eval() 函数中像 Java 程序中同样的方式来调用这个实例的方法。同样的,假设我们有一个脚本函数,它进行一定的计算并返回值,我们 在 Java 代码中也可以方便的调用这一脚本:
-
- package tony;
-
- import javax.script.Invocable;
- import javax.script.ScriptEngine;
- import javax.script.ScriptEngineManager;
- import javax.script.ScriptException;
-
- public class TestInv {
- public static void main(String[] args) throws ScriptException,
- NoSuchMethodException {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("JavaScript");
- String script = "function say(first,second) { print(first +' '+ second); }";
- engine.eval(script);
- Invocable inv = (Invocable) engine;
- inv.invokeFunction("say", "Hello", "Tony");
- }
- }
-
-
-
-
- 在 这个例子中我们首先定义了一个脚本函数 say,它的作用是接受两个字符串参数将他们拼接并返回。这里我们第一次遇到了 ScriptEngine 的两 个可选接口之一 —— Invocable,Invocable 表示当前的 engine 可以作为函数被调用。这里我们将 engine 强制转换 为 Invocable 类型,使用 invokeFunction 方法将参数传递给脚本引擎。invokeFunction这个方法使用了可变参数的 定义方式,可以一次传递多个参数,并且将脚本语言的返回值作为它的返回值。下面这个例子用JavaScript实现了一个简单的max函数,接受两个参 数,返回较大的那个。为了便于断言结果正确性,这里继承了JUnit Testcase,关于JUnit请参考www.junit.org。
-
- package tony;
-
- import javax.script.Invocable;
- import javax.script.ScriptEngine;
- import javax.script.ScriptEngineManager;
- import javax.script.ScriptException;
- import junit.framework.TestCase;
-
- public class TestScripting extends TestCase {
-
- public void testInv() throws ScriptException, NoSuchMethodException {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("JavaScript");
- String script = "function max(first,second) "
- + "{ return (first > second) ?first:second;}";
- engine.eval(script);
- Invocable inv = (Invocable) engine;
- Object obj = inv.invokeFunction("max", "1", "0");
- assertEquals("1", obj.toString());
- }
- }
-
-
-
-
- Invocable 接口还有一个方法用于从一个 engine 中得到一个 Java Interface 的实例,它的定义如下:
-
- <T> T getInterface(Class<T> clasz)
-
-
-
-
- 它 接受一个 Java 的 Interface 类型作为参数,返回这个 Interface 的一个实例。也就是说你可以完全用脚本语言来写一 个 Java Interface 的所有实现。以下是一个例子。首先定一了个 Java Interface,它有两个简单的函数,分别为求最大值和最 小值:
-
- package tony;
-
- public interface MaxMin {
- public int max(int a, int b);
- public int min(int a, int b);
- }
-
-
-
-
- 这个 Testcase 用 JavaScript 实现了 MaxMin 接口,然后用 getInterface 方法返回了一个实例并验证了结果。
-
- public void testInvInterface() throws ScriptException,
- NoSuchMethodException {
- ScriptEngineManager factory = new ScriptEngineManager();
- ScriptEngine engine = factory.getEngineByName("JavaScript");
- String script = "function max(first,second) "
- + "{ return (first > second) ?first:second;}";
- script += "function min(first,second) { return (first < second) ?first:second;}";
- engine.eval(script);
- Invocable inv = (Invocable) engine;
- MaxMin maxMin = inv.getInterface(MaxMin.class);
- assertEquals(1, maxMin.max(1, 0));
- assertEquals(0, maxMin.min(1, 0));
- }
-
-
-
-
- 脚本的编译执行
-
- 到 目前为止,我们的脚本全部都是解释执行的,相比较之下编译执行将会获得更好的性能。这里将介绍 ScriptEngine 的另外一个可选接 口 —— Compilable,实现了这一接口的脚本引擎支持脚本的编译执行。下面这个例子实现了一个判断给定字符串是否是 email 地址或 者 ip 地址的脚本:
-
- public void testComplie() throws ScriptException {
- ScriptEngineManager manager = new ScriptEngineManager();
- ScriptEngine engine = manager.getEngineByName("JavaScript");
- String script = "var email=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]"
- + "+(//.[a-zA-Z0-9_-]+)+$/;";
- script += "var ip = /^(//d{1,2}|1//d//d|2[0-4]//d|25[0-5])"
- +"(//.(//d{1,2}|1//d//d|2[0-4]//d|25[0-5])){3}$/;";
- script += "if(email.test(str)){println('it is an email')}"
- + "else if(ip.test(str)){println('it is an ip address')}"
- + "else{println('I don//'t know')}";
- engine.put("str", "email@address.tony");
- Compilable compilable = (Compilable) engine;
- CompiledScript compiled = compilable.compile(script);
- compiled.eval();
- }
-
-
-
-
- 脚 本编译的过程如下:首先将 engine 转换为 Compilable 接口,然后调用 Compilable 接口的 compile 方法得到一 个 CompiledScript 的实例,这个实例就代表一个编译过的脚本,如此用 CompiledScript 的 eval 方法即为调用编译好 的脚本了。在我的 Think Pad 上,这段代码编译后的调用大约比直接调用 engine.eval 要快 3-4 倍。随着脚本复杂性的提升,性 能的提升会更加明显。
-
- 脚本上下文与绑定
-
- 真正将脚本语言与 Java 联系起来的不是 ScriptEngine,而是 ScriptContext,它作为 Java 与 ScriptEngine 之间的桥梁而存在。
-
- 一 个 ScriptEngine 会有一个相应的 ScriptContext,它维护了一个 Map,这个 Map 中的每个元素都是脚本语言对象 与 Java 对象之间的映射。同时这个 Map 在我们的 API 中又被称为 Bindings。一个 Bindings 就是一个限定 了 key 必须为 String 类型的 Map —— Map<String, Object>。所以一 个 ScriptContext 也会有对应的一个 Bindings,它可以通过 getBindings 和 setBindings 方法来获取和 更改。
-
- 一个 Bindings 包括了它的 ScriptContext 中的所有脚本变量,那么如何获取脚本变量的值呢?当然,从 Bindings 中 get 是一个办法,同时 ScriptContext 也提供了 getAttribute 方法,在只希望获得某一特定脚本变量值的时候它显然是十分有效的。相应地 setAttribute 和 removeAttribute 可以增加、修改或者删除一个特定变量。
-
- 在 ScriptContext 中 存储的所有变量也有自己的作用域,它们可以是 ENGINE_SCOPE 或者是 GLOBAL_SCOPE,前者表示这 个 ScriptEngine 独有的变量,后者则是所有 ScriptEngine 共有的变量。例如我们执 行 engine.put(key, value) 方法之后,这时便会增加一个 ENGINE_SCOPE 的变量,如果要定义一 个 GLOBAL_SCOPE 变量,可以通 过 setAttribute(key, value, ScriptContext.GLOBAL_SCOPE) 来完成。
-
- 此外 ScriptContext 还提供了标准输入和输出的重定向功能,它可以用于指定脚本语言的输入和输出。
-
-
-
-
-
-
- 回页首
-
-
-
-
- 在 JavaScript 中使用 Java 高级特性
-
- 这一部分不同于前述内容,将介绍 JavaScript引擎 —— Rhino 独有的特性。
-
- 使用 Java 对象
-
- 前 面的部分已经介绍过如何在 JavaScript 中使用一个已经实例化的 Java 对象,那么如何在 JavaScript 中去实例化一 个 Java 对象呢?在 Java 中所有 Class 是按照包名分层次存放的,而在 JavaScript 没有这一结构,Rhino 使用了一个 巧妙的方法实现了对所有 Java 对象的引用。Rhino 中定义了一个全局变量—— Packages,并且它的所有元素也是全局变量,这个全局变量 维护了 Java 类的层次结构。例如 Packages.java.io.File 引用了 Java 的 io 包中 File 对象。如此一来我们 便可以在 JavaScript 中方便的使用 Java 对象了,new 和 Packages 都是可以被省略的:
-
-
- var frame = java.io.File("filename");
-
-
-
-
- 我们也可以像 Java 代码中一样把这个对象引用进来:
-
- importClass (java.io.File);
- var file = File("filename");
-
-
-
-
- 如果要将整个包下的所有类都引用进来可以用 importPackage:
-
- importPackage(java.io);
-
-
-
-
- 如果只需要在特定代码段中引用某些包,可以使用 JavaImporter 搭配 JavaScript 的 with 关键字,如:
-
- var MyImport = JavaImporter(java.io.File);
- with (MyImport) {
- var myFile = File("filename");
- }
-
-
-
-
- 用户自定义的包也可以被引用进来,不过这时候 Packages 引用不能被省略:
-
- importPackage(Packages.tony);
- var hello = HelloWorld();
- hello.sayHello();
-
-
-
-
- 注意这里只有 public 的成员和方法才会在 JavaScript 中可见,例如对 hello.s 的引用将得到 undefined。下面简单介绍一些常用的特性:
-
- 使用 Java 数组
-
- 需要用反射的方式构造:
-
- var a = java.lang.reflect.Array.newInstance(java.lang.String, 5);
-
-
-
-
- 对于大部分情况,可以使用 JavaScript 的数组。将一个 JavaScript 的数组作为参数传递给一个 Java 方法时 Rhino 会做自动转换,将其转换为 Java 数组。
-
- 实现一个 Java 接口
-
- 除了上面提到的 Invocable 接口的 getInterface 方法外,我们也可以在脚本中用如下方式:
-
-
- obj={max:function(a,b){return (a > b) ?a:b;}};
-
- maxImpl=com.tony.MaxMin(obj);
-
- print (maxImpl.max(1,2));
-
-
-
-
- 如果接口只有一个方法需要实现,那么在 JavaScript 中你可以传递一个函数作为参数:
-
- function func(){
- println("Hello World");
- }
- t=java.lang.Thread(func);
- t.start();
-
-
-
-
- 对于 JavaBean 的支持
-
- Rhino 对于 JavaBean 的 get 和 is 方法将会自动匹配,例如调用 hello.string,如果不存在 string 这个变量,Rhino 将会自动匹配这个实例的 isString 方法然后再去匹配 getString 方法,若这两个方法均不存在才会返回 undefined。
-
-
-
-
-
-
- 回页首
-
-
-
-
- 命令行工具 jrunscript
-
- 在 Mustang 的发行版本中还将包含一个脚本语言的的命令行工具,它能够解释所有当前 JDK 支持的脚本语言。同时它也是一个用来学习脚本语言很好的工具。你可以在http:
-
-
-
-
-
-
- 回页首
-
-
-
-
- 结束语
-
- 脚 本语言牺牲执行速度换来更高的生产率和灵活性。随着计算机性能的不断提高,硬件价格不断下降,可以预见的,脚本语言将获得更广泛的应用。 在 JavaSE 的下一个版本中加入了对脚本语言的支持,无疑将使 Java 程序变得更加灵活,也会使 Java 程序员的工作更加有效率。
-
-
-
-
- 参考资料
-
- JSR 233 主页http:
-
-
- Mozilla Rhino 项目主页http:
-
-
- https:
-
-
- http:
-
-
- http:
-
-
- http:
-
-
-
- 关于作者
-
-
-
- 吴玥颢,目前就职于 IBM 中国开发中心 Harmony 开发团队。 除了对 Java 和脚本语言的热爱之外,他的兴趣还包括哲学、神话、历史与篮球。此外他还是个电脑游戏高手。您可以通过wuyuehao@cn.ibm.com联系到他。
-
-
-
-
-
-
- 原文地址 http:
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
要在Java中运行JavaScript,首先需要引入支持JavaScript的引擎,如Nashorn(在Java 8中默认提供,但在Java 11后被废弃)或Rhino。如果使用Nashorn,通常不需要额外的库,因为它已经包含在Java标准版中。若选择Rhino...
以下是一个简单的示例,展示如何使用Nashorn引擎在Java中运行JavaScript代码: ```java import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public ...
Java到JavaScript转换工具有助于开发者将已有的Java代码库移植到JavaScript环境中,这在Web开发中尤其有用,因为JavaScript是浏览器端的主要脚本语言。这样的工具能够帮助开发者利用Java的强大功能来构建前端应用,...
这个项目可能是一个库或者框架,它不含任何第三方依赖,因此可以在纯JavaScript环境中独立运行。"Java"标签可能意味着项目同时也提供了与Java平台的接口或适配器,使得Java开发者也能方便地使用这个库。 描述中的...
反之,JavaScript计算的结果也可以通过`eval()`返回给Java。 描述中提到的“逻辑可配”意味着这种跨语言调用方式特别适用于那些需要根据应用环境动态改变的业务逻辑。例如,你可以在Java服务端定义一个接口,该接口...
6. Nashorn引擎特性:Nashorn引擎是Java中的JavaScript运行时,提供了一种方式让Java应用程序执行JavaScript代码。它包括了ECMAScript 5.1的完整实现,还支持一些扩展特性。 7. JDK中的JavaScript支持:从内容中...
",展示了如何在Java中使用Rhino执行简单的JavaScript。 Rhino还提供了`Context`类,它提供了更底层的API来控制JavaScript环境的各个方面,如错误处理、优化级别等。此外,Rhino支持动态加载JavaScript文件,这样...
- **Java转JavaScript**: 这一过程涉及到的技术主要是指如何将原本基于Java语言编写的代码转换为能够在浏览器环境中运行的JavaScript代码。这项技术对于希望利用Java的强大特性和广泛的库资源来构建前端Web应用的...
JavaApplet 和 JavaScript 都是在 Web 开发中非常重要的技术。JavaApplet 提供了强大的功能,如多媒体处理和网络通信,而 JavaScript 则更侧重于前端的交互性和动态性。通过结合使用这两种技术,开发者能够构建出...
安装JRE6后,用户可以运行基于Java 1.6或更低版本编写的程序,包括桌面应用、Web应用以及Java小程序(Applet)。值得注意的是,随着技术的发展,JRE的更新版本不断推出,以修复已知问题和提升安全性,因此,尽管JRE6...
* 在Java中使用脚本语言JavaScript。 * * @author LeiWen@FansUnion.cn,http://FansUnion.cn, * http://blog.csdn.net/FansUnion * * QQ:240370818 参考资料:...
在JavaScript中,还有ES6(ECMAScript 6,也称ES2015)及后续版本引入的新特性,如类和模块系统、箭头函数、模板字符串、解构赋值、Promise对象等,这些都极大地提升了代码的可读性和维护性。 "Java专用下载"标签...
在Java中,我们可以使用`Runtime`类或`ProcessBuilder`类来执行命令行操作。 1. **使用Runtime.exec()** `Runtime.getRuntime().exec(command)` 是最基础的方法,用于执行指定的系统命令。`command`参数是一个字符...
在Java中,可以使用`javax.crypto`包来实现DES加密解密。首先,创建一个KeyGenerator对象,设置为DES算法,然后生成密钥。接着,创建Cipher对象,初始化为加密或解密模式,并使用密钥。最后,调用`doFinal()`方法...
在这个平台上,你可以找到关于如何在Java中使用JavaScript的官方文档和工具。 5. Oracle官方文档:Oracle提供了Java的官方文档,其中包含了关于在Java中使用JavaScript的指南。文档编号为E94834-02,发布于2018年11...
除了从 JavaScript 访问 Java Applet 外,还可以在 Java Applet 中使用 JavaScript。这主要是通过 Java 的 `ScriptEngineManager` 类来实现的。以下是一个基本的步骤说明: 1. **引入必要的类库**:在 Java Applet ...
在这个综合项目中,我们将深入探讨四种核心技术:JavaServer Pages(JSP)、Java、Servlet以及JavaScript,它们都是构建动态Web应用程序的关键组件。这些技术协同工作,为用户提供丰富的交互式体验,同时在后端处理...
同时,JavaScript也有许多强大的服务器端框架(如Node.js),这使得Doppio可以在服务器端预处理Java字节码,进一步提高性能。 总结,Doppio 是一个在浏览器上运行Java程序的创新解决方案,它通过JavaScript实现了...
如果需要在Java中执行JavaScript代码,可以使用`evaluateJavaScript`方法: ```java webView.evaluateJavaScript("alert('Hello, JavaScript!')", null); ``` 第一个参数是JavaScript代码,第二个参数是一个回...
当JavaScript执行完毕并准备好将结果返回给Java时,它会通过window.stub.jsMethod(result)来调用Java中相应的方法,并传递一个参数result。 在JavaScript代码中,可以使用window.stub.jsMethod()来调用Java的方法。...