iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何深入浅出Rhino以及与Java和JS的关系
  • 146
分享到

如何深入浅出Rhino以及与Java和JS的关系

2023-06-17 12:06:33 146人浏览 薄情痞子
摘要

这期内容当中小编将会给大家带来有关如何深入浅出Rhino以及与Java和js的关系,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java SE的亮点之一就是oracle详细阐述Java SE 8路线图。我

这期内容当中小编将会给大家带来有关如何深入浅出Rhino以及与Java和js的关系,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Java SE的亮点之一就是oracle详细阐述Java SE 8路线图。我们先来看看Java SE 8新增了哪些主要功能:

Java SE 8 新增主要功能

为提高开发人员工作效率,更好地利用多核处理器和增强对Java集合apis的大容量数据处理功能,推出的Lambda表达式(“关闭”)。

原始Java模块系统(“项目Jigsaw”)将简化应用程序的构建、包装以及部署,让一个完全模块化的Java平台能在服务器、客户和嵌入式系统上进行定制化部署。

JVM上的javascript改进,包括一个为JVM优化的全新JavaScript引擎Nashorn和全面的Java / JavaScript互操作性。

具有JavaFX 3.0形式的下一代Java客户端。包括多点触摸功能的现代设备支持。

完成的HotSpot / JRockit JVM集聚项目,包括性能增强和第二代的Java Flight Recorder。

其中,笔者最关心的是第三条,即JVM对JavaScript的改进。它的核心组件是JavaScript引擎Nashorn,它实现了Java与JavaScript互操作性。Nashorn一词与Rhino类似,汉语意思均为犀牛。而巧合的是,Rhino就是JavaScript引擎,它的目的就是实现Java与JavaScript的互操作性。那么Rhino究竟是什么呢?为什么说Nashorn是新一代JavaScript引擎?Rhino有什么特性?Rhino与Java及JavaScript有什么关系呢?下面将会为您一一解答。

什么是Rhino?

Rhino 是JavaScript 的一种基于Java的实现,原先由Mozilla开发,现在被集成进入jdk 6.0。下面这两行代码恰好说明了这一点。

import sun.org.mozilla.javascript.internal.Context;  import sun.org.mozilla.javascript.internal.Scriptable;

Rhino汉语意思为犀牛,它的名字来源于 O'Reilly 关于 JavaScript 的书的封面,如图一所示。

如何深入浅出Rhino以及与Java和JS的关系

图一 “犀牛“的来源

Rhino的特点如下:

JavaScript 1.5的全部特性

◆ 允许使用脚本直接操作Java

◆ 提供JavaScript shell执行其它JavaScript脚本

◆ 提供JavaScript编译器将JavaScript源程序转换成Java类文件

Rhino相关背景

Rhino的历史可追溯到1997 年。Netscape计划开发Java版的Navigator,即Javagator。它也就是 Rhino 的前身。虽然 Javagator 未能开花结果,但是Rhino,作为Netscape 对 JavaScript 的移植语言,经过时间考验存活了下来。

如今,随着 Rhino 开放源代码,越来越多的开发者参与了 Rhino 的开发。随着Rhino的愈加成熟,越来越多的用户选择使用了Rhino。

Rhino语言特点

Java是一种面对对象的编译型语言。它首先将源代码编译成二进制字节码(bytecode),然后依赖各种不同平台上的虚拟机来解释执行字节码,从而实现了“一次编译、到处执行”的跨平台特性。

JavaScript是一种动态、弱类型、基于原型的客户端脚本语言。JavaScript 包括一个基于对象的 API,称为文档对象模型(Document Object Model)或 DOM,用以访问和操作 WEB 页面的内容,给html网页添加动态功能。

Rhino是一个介于Java与JavaScript之间的语言。它的基础是 Java 语言,这使得它简单易学,但相比于JavaScript脚本语言来说,它又太过复杂。不过,Rhino 的主要缺点也正是它的强大之处,Rhino 是一种轻量级的、功能强大的脚本语言。Rhino 使用原型而不是类,这使它比很多脚本语言更适合开发 GUI 应用程序,在考虑性能和风格等因素时更是如此。

Rhino语言特点的优缺点

一方面,作为一种动态类型的、基于原型的脚本语言,Rhino借用了很多JavaScript语法。比如,Rhino不再使用语句结束符( ; ),放宽了变量声明规则,并且极大地简化了修改和检索对象属性的语法。另一方面,作为JavaScript 的Java实现,Rhino语法非常类似于Java编程语言。比如,Rhino采用了与 Java 编程语言相似的循环和条件结构,并且遵循类似的语法模式来表示这些结构。

Rhino 和 Java 语言之间有一些显著的区别。Rhino 是一种基于原型的(prototype-based)语言,而不是一种基于类的(class-based)语言。Rhino中,函数和变量的声明中看不到类型,取而代之的是,使用 function关键字声明函数,使用 var关键字声明局部变量。

Rhino的原始想法是将JavaScript 编译成Java字节码执行,即采用编译执行的方式。由于由于JVM存在垃圾收集、编译和装载过程的开销过大等限制,Rhino采用了解释执行的方式。

如何下载Rhino安装包

用户可以从官网Http://www.mozilla.org/rhino/ 下载Rhino,笔者下载的版本为rhino1.7R3.zip。

其中,主要的目录与文件的如下:

Src:Rhino相关jar包对应的源代码

Javadoc:Rhino相关Jar包对应的Java说明文档

Examples:Rhino相关示例

build.xml:Rhino工程对应的Ant文件

js.jar:Rhino对应的Jar包

Rhino环境配置

在使用之前,我们需要配置环境及运行js脚本。具体如下:

将下载包中的js.jar文件加入系统CLASSPATH中。

运行js解释器java org.mozilla.javascript.tools.shell.Main。进入交互模式:

Rhino 1.7 release 3 2011 05 09   js>

注:***行为js解释器的版本号,后面跟着提示符 js>

下面我们将利用js shell,使用JavaScript操纵Java对象。

JavaScript操纵Java对象

1. Rhino如何访问Java包与类文件

Java语法规定,任何代码都必须以class文件的形式存在,而每个class文件必须属于一个package,默认为default。而JavaScript并没有类似package的层级结构概念,那么如何使用Rhino访问Java类文件呢?

Rhino定义了一个top-level变量Packages。变量Packages对应的所有属性均对应Java包名。比如,我们需要访问某一个Java的Package com.example.

js> Packages.com.example  [JavaPackage com.example]

简单起见,我们也可以去掉变量Packages,直接输入Java包名。因此,上述Package com.example等价与com.example,如下:

js> com.example   [JavaPackage com.example]

刚才演示了如何通过js shell访问Java包,访问Java类的方式类似。假如我们需要访问标准的Java 文件类java.io.File,如下。

 js> java.io.File  [JavaClass java.io.File]

或者,为避免输入全名,我们先导入包,然后输入Class类名,如下:

js> importPackage(java.io)   js> File   [JavaClass java.io.File]

这里的importPackage(java.io),在效果上等价于Java声明import java.io.*; 不同的是,Java会隐式import java.lang.*,而Rhino不会。因为Rhino定义的对象Boolean, Math, Number, Object, String等与Java语法完全不同,两者无法等价。

这里需要注意的是,Rhino对该语法的错误处理机制,当被访问的类存在时,Rhino加载该class,而当其不存在时,则把它当成package名称,而并不会报错。例如,当访问一个不存在的类com.example.AAA时,输入如下。

js> com.example.AAA  [JavaPackage com.example.AAA]

仅当访问类AAA时,Rhino才会报错。

2. Rhino如何与Java对象交互

与Java类似,Rhino使用new操作符创建对象。

js> new java.util.Date()   Thu Nov 03 16:19:04 CST 2011

可以使用JavaScript变量存储Java对象,并调用其方法,如下:

 js> f = new java.io.File("sample.txt")   sample.txt   js> f.isDirectory()   false

对于static方法与变量,调用如下:

js> java.lang.Math.PI

141592653589793

js> java.lang.Math.cos(0)

1

在JavaScript中,方法本身就是对象,这一点与Java不同。我们可以通过下列方式查看方法的重载:

js> f.listFiles  function listFiles() {}

输出中列出三个重载方法。***个为无参函数,第二与第三个对应的参数分别为FilenameFilter与FileFilter。

另一个比较有意思的特点是通过构造for..in,查看对象对应的所有方法与变量。如下:

js> for (i in f) { print(i) }  exists  parentFile  mkdir  toString  wait  [44 others]

这里列出的方法一部分来自于父类,比如wait来自父类java.lang.Object。

对于JavaBean,Rhino也提供按名字访问的简单方式。比如,通过下面这种方式,我们就可以调用File对象的getName与isDirectory方法:

 js> f.name   test.txt  js> f.directory   false

3. Rhino如何实现Java接口

JavaScript当中,方法本身就是对象。下面我们通过JavaScript语法{propertyName: value}声明一个JavaScript方法,并调用该方法如下:

 js> obj = { run: function () { print("\nrunning"); } }   [object Object]   js> obj.run()   running

现在我们构造一个JavaScript对象,实现Runnable接口。并将该对象作为参数,构造一个新的线程,并启动该线程。

 js> r = new java.lang.Runnable(obj);  adapter1@291aff  js> t = new java.lang.Thread(r)  Thread[Thread-0,5,main]  js> t.start()  js> running

***的js>提示符与新线程的打印输出running的先后顺序是随机的,取决于线程的调度策略。

后端的处理流程来讲,Rhino首先为Runnable接口的实现类生成Java字节码文件。然后调用JavaScript对象定义的Run方法。

4. Rhino如何创建Java 数组

Rhino使用Java的发射机制生成数组。下面是生成2个String对象的代码:

 js> array = java.lang.reflect.Array.newInstance(java.lang.String, 2);  [Ljava.lang.String;@a20892  js> array[0] = "Double"  Double  js> array[1] = "Life"  Life  js> array[0] + array[1]  DoubleLife   js>

5. Rhino如何捕获与处理异常

与Java类似,Rhino使用try...catch关键字处理异常。

 js> 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");  }  } > > > > > > > > js> classForName("NonExistinGClass");  Class NonExistingClass not found  js> classForName(null);  Class name is null

6. Rhino如何调用js文件

当然,除了在命令行的方式,我们还可以使用操纵JavaScript文件。下面是一段JavaScript代码,主要目的是判断该数是否为质数。代码如下:

function isPrime (num)  {  if (num <= 1) {  print("Enter an integer no less than 2.")  return false  }  var prime = true var sqrRoot = Math.round(Math.sqrt(num))  for (var n = 2; prime & n <= sqrRoot; ++n) {  prime = (num % n != 0)  }  return prime  }

我们保存文件为C:\isPrime.js。然后我们需要调用load方法加载该脚本。***,我们可以调用isPrime方法来判断是否为质数。

js> load("C:/isPrime.js")  js> isPrime(33);  false  js> isPrime(31)  true

需要注意的是,注意:文件分隔符需要调整,是“/”而不是“\”。

上述部分示例可以参见Rhino官方网站https://developer.mozilla.org/en/Scripting_Java。另外examples目录下很多例子都值得参考与学习

刚才使用JavaScript操纵Java对象。接下来我们看看如何使用Java程序访问JavaScript

Java对象操纵JavaScript

下面是一段Java代码,用来运行数学表达式。代码如下:

package com.example;  import sun.org.mozilla.javascript.internal.Context;  import sun.org.mozilla.javascript.internal.Scriptable;  publicclass Test {  publicstaticvoid main(String[] args) {  Context cx = Context.enter();  try {  Scriptable scope = cx.initStandardObjects();  String str = "3/(1+2)";  Object result = cx.evaluateString(scope, str, null, 1, null);  System.out.println(str + "=" + Context.toNumber(result));  } finally {  Context.exit();  }  }  }

运行Java com.example.Test,输出结果如下:

3/(1+2)=1.0

之所以是1.0而不是1,是因为Context.toNumber(result)返回的类型为double。另一个值得注意的是,这里import的package属于JDK 6.0。因此,在不需要Rhino提供的js.jar,该程序仍能独立运行。

虽然Rhino作为JavaScript运行时,功能非常强大,但在性能上却无法与其他的JavaScript运行时(比如Google Chrome的V8 JavaScript Engine)相提并论。值得注意的是,JRuby专家Charles Oliver Nutter也开始参与Rhino项目中,以提升Rhino JavaScript运行时的速度,进而实现与V8的竞争。而Oracle在对JVM上的JavaScript改进与优化,我们有理由期待,在未来,新一代JavaScript运行时Nashorn的速度将会得到极大的提升。

上述就是小编为大家分享的如何深入浅出Rhino以及与Java和JS的关系了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: 如何深入浅出Rhino以及与Java和JS的关系

本文链接: https://www.lsjlt.com/news/288902.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何深入浅出Rhino以及与Java和JS的关系
    这期内容当中小编将会给大家带来有关如何深入浅出Rhino以及与Java和JS的关系,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Java SE的亮点之一就是Oracle详细阐述Java SE 8路线图。我...
    99+
    2023-06-17
  • 如何解决js数据类型和引用类型以及深浅拷贝和内存分配问题
    本篇文章给大家分享的是有关如何解决js数据类型和引用类型以及深浅拷贝和内存分配问题,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。js 深浅拷贝...
    99+
    2024-04-02
  • 如何理解.NET框架与COM的背景和历史以及关系的发展
    今天就跟大家聊聊有关如何理解.NET框架与COM的背景和历史以及关系的发展,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。.NET框架与COM:背景和历史可复用软件不是一个新概念。八年...
    99+
    2023-06-17
  • 如何深入理解Java多线程与并发框中的volatile关键字
    本篇文章为大家展示了如何深入理解Java多线程与并发框中的volatile关键字,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。概念把对 volatile变量的单个读/写,看成是使用 同一个监视器锁 ...
    99+
    2023-06-05
  • 如何理解HTML开发中.html和.htm和.shtml以及.shtm的区别与联系
    如何理解HTML开发中.html和.htm和.shtml以及.shtm的区别与联系,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。大家都知道,我们每天浏览的网页或者网站或者w...
    99+
    2023-06-08
  • JS如何使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能
    这篇文章给大家分享的是有关JS如何使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体如下:HTML部分:<div ...
    99+
    2024-04-02
  • 如何深入理解Java多线程与并发框中线程和进程的区别
    如何深入理解Java多线程与并发框中线程和进程的区别,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。线程和进程的区别1. 资源调度单位在计算机中,进程是程序运行所...
    99+
    2023-06-05
  • 如何通过优化预读文件设置来对Win7和Vista以及XP系统的开关机提速
    今天就跟大家聊聊有关如何通过优化预读文件设置来对Win7和Vista以及XP系统的开关机提速,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。如何通过优化预读文件设置,来对Win7/Vi...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作