小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

深入淺出Rhino:Java與JS互操作

 CevenCheng 2013-08-27

深入淺出Rhino:Java與JS互操作

2011年11月11日00:00 it168網(wǎng)站原創(chuàng) 作者:DoubleLife 編輯:皮麗華 我要評論(0)
標簽: Java , javascript

    【IT168 專稿】2011年10月6日,一年一度的JavaOne大會隆重舉行。JavaOne2011大會的主題之一介紹針對不同Java平臺的產(chǎn)品路線圖,這其中包括移動版(ME,Micro Edition)、標準版(SE,Standard Edition)以及企業(yè)版(EE,Enterprise Edition)。

  Java SE的亮點之一就是Oracle詳細闡述Java SE 8路線圖。我們先來看看Java SE 8新增了哪些主要功能:

  Java SE 8 新增主要功能

  1、為提高開發(fā)人員工作效率,更好地利用多核處理器和增強對Java集合APIs的大容量數(shù)據(jù)處理功能,推出的Lambda表達式(“關(guān)閉”)。

  2、原始Java模塊系統(tǒng)(“項目Jigsaw”)將簡化應(yīng)用程序的構(gòu)建、包裝以及部署,讓一個完全模塊化的Java平臺能在服務(wù)器、客戶和嵌入式系統(tǒng)上進行定制化部署。

  3、在JVM上的JavaScript改進,包括一個為JVM優(yōu)化的全新JavaScript引擎Nashorn和全面的Java / JavaScript互操作性。

  4、具有JavaFX 3.0形式的下一代Java客戶端。包括多點觸摸功能的現(xiàn)代設(shè)備支持。

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

  其中,筆者最關(guān)心的是第三條,即JVM對JavaScript的改進。它的核心組件是JavaScript引擎Nashorn,它實現(xiàn)了Java與JavaScript互操作性。Nashorn一詞與Rhino類似,漢語意思均為犀牛。而巧合的是,Rhino就是JavaScript引擎,它的目的就是實現(xiàn)Java與JavaScript的互操作性。那么Rhino究竟是什么呢?為什么說Nashorn是新一代JavaScript引擎?Rhino有什么特性?Rhino與Java及JavaScript有什么關(guān)系呢?本文將會為您一一解答。

  什么是Rhino?

  Rhino 是 JavaScript 的一種基于Java的實現(xiàn),原先由Mozilla開發(fā),現(xiàn)在被集成進入JDK 6.0。下面這兩行代碼恰好說明了這一點。

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

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

  Rhino漢語意思為犀牛,它的名字來源于 O'Reilly 關(guān)于 JavaScript 的書的封面,如圖一所示。

 

深入淺出Rhino:實現(xiàn)Java與JS的互操作

  圖一 “犀?!暗膩碓?/p>

  Rhino的特點如下:

  •   JavaScript 1.5的全部特性
  •   允許使用腳本直接操作Java
  •   提供JavaScript Shell執(zhí)行其它JavaScript腳本
  •   提供JavaScript編譯器將JavaScript源程序轉(zhuǎn)換成Java類文件

  Rhino相關(guān)背景

  Rhino的歷史可追溯到1997 年。Netscape計劃開發(fā)Java版的Navigator,即Javagator。它也就是 Rhino 的前身。雖然 Javagator 未能開花結(jié)果,但是Rhino,作為Netscape 對 JavaScript 的移植語言,經(jīng)過時間考驗存活了下來。

  如今,隨著 Rhino 開放源代碼,越來越多的開發(fā)者參與了 Rhino 的開發(fā)。隨著Rhino的愈加成熟,越來越多的用戶選擇使用了Rhino。

  Rhino語言特點

  Java是一種面對對象的編譯型語言。它首先將源代碼編譯成二進制字節(jié)碼(bytecode),然后依賴各種不同平臺上的虛擬機來解釋執(zhí)行字節(jié)碼,從而實現(xiàn)了“一次編譯、到處執(zhí)行”的跨平臺特性。

  JavaScript是一種動態(tài)、弱類型、基于原型的客戶端腳本語言。JavaScript 包括一個基于對象的 API,稱為文檔對象模型(Document Object Model)或 DOM,用以訪問和操作 Web 頁面的內(nèi)容,給HTML網(wǎng)頁添加動態(tài)功能。

  Rhino是一個介于Java與JavaScript之間的語言。它的基礎(chǔ)是 Java 語言,這使得它簡單易學(xué),但相比于JavaScript腳本語言來說,它又太過復(fù)雜。不過,Rhino 的主要缺點也正是它的強大之處,Rhino 是一種輕量級的、功能強大的腳本語言。Rhino 使用原型而不是類,這使它比很多腳本語言更適合開發(fā) GUI 應(yīng)用程序,在考慮性能和風(fēng)格等因素時更是如此。

  Rhino語言特點的優(yōu)缺點

  一方面,作為一種動態(tài)類型的、基于原型的腳本語言,Rhino借用了很多JavaScript語法。比如,Rhino不再使用語句結(jié)束符( ; ),放寬了變量聲明規(guī)則,并且極大地簡化了修改和檢索對象屬性的語法。另一方面,作為JavaScript 的Java實現(xiàn),Rhino語法非常類似于Java編程語言。比如,Rhino采用了與 Java 編程語言相似的循環(huán)和條件結(jié)構(gòu),并且遵循類似的語法模式來表示這些結(jié)構(gòu)。

  Rhino 和 Java 語言之間有一些顯著的區(qū)別。Rhino 是一種基于原型的(prototype-based)語言,而不是一種基于類的(class-based)語言。Rhino中,函數(shù)和變量的聲明中看不到類型,取而代之的是,使用 function關(guān)鍵字聲明函數(shù),使用 var關(guān)鍵字聲明局部變量。

  Rhino的原始想法是將JavaScript 編譯成Java字節(jié)碼執(zhí)行,即采用編譯執(zhí)行的方式。由于由于JVM存在垃圾收集、編譯和裝載過程的開銷過大等限制,Rhino采用了解釋執(zhí)行的方式。

  如何下載Rhino安裝包

  用戶可以從官網(wǎng)http://www.mozilla.org/rhino/ 下載Rhino,筆者下載的版本為rhino1.7R3.zip。

  其中,主要的目錄與文件的如下:

  Src:Rhino相關(guān)Jar包對應(yīng)的源代碼

  Javadoc:Rhino相關(guān)Jar包對應(yīng)的Java說明文檔

  Examples:Rhino相關(guān)示例

  build.xml:Rhino工程對應(yīng)的Ant文件

  js.jar:Rhino對應(yīng)的Jar包

 


【IT168 專稿】Rhino環(huán)境配置

  在使用之前,我們需要配置環(huán)境及運行js腳本。具體如下:

  1、 將下載包中的js.jar文件加入系統(tǒng)CLASSPATH中。

  2、 運行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語法規(guī)定,任何代碼都必須以class文件的形式存在,而每個class文件必須屬于一個package,默認為default。而JavaScript并沒有類似package的層級結(jié)構(gòu)概念,那么如何使用Rhino訪問Java類文件呢?

  Rhino定義了一個top-level變量Packages。變量Packages對應(yīng)的所有屬性均對應(yīng)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]

 

  或者,為避免輸入全名,我們先導(dǎo)入包,然后輸入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操作符創(chuàng)建對象。

  js> new java.util.Date()

  Thu Nov 
03 16:19:04 CST 2011

 

  可以使用JavaScript變量存儲Java對象,并調(diào)用其方法,如下:

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

  sample.txt

  js
> f.isDirectory()

  
false

 

  對于static方法與變量,調(diào)用如下:

js> java.lang.Math.PI

  3.141592653589793

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

  1


    【IT168 專稿】在JavaScript中,方法本身就是對象,這一點與Java不同。我們可以通過下列方式查看方法的重載:

js> f.listFiles

  
function listFiles() {/*

  java.io.File[] listFiles()

  java.io.File[] listFiles(java.io.FilenameFilter)

  java.io.File[] listFiles(java.io.FileFilter)

  
*/}

  輸出中列出三個重載方法。第一個為無參函數(shù),第二與第三個對應(yīng)的參數(shù)分別為FilenameFilter與FileFilter。

  另一個比較有意思的特點是通過構(gòu)造for..in,查看對象對應(yīng)的所有方法與變量。如下:

  js> for (i in f) { print(i) }

  exists

  parentFile

  mkdir

  toString

  wait

  [
44 others]

  這里列出的方法一部分來自于父類,比如wait來自父類java.lang.Object。

  對于JavaBean,Rhino也提供按名字訪問的簡單方式。比如,通過下面這種方式,我們就可以調(diào)用File對象的getName與isDirectory方法:

 

  js> f.name

  test.txt

  js
> f.directory

  
false

 

  3. Rhino如何實現(xiàn)Java接口

  JavaScript當中,方法本身就是對象。下面我們通過JavaScript語法{propertyName: value}聲明一個JavaScript方法,并調(diào)用該方法如下:

  js> obj = { run: function () { print("\nrunning"); } }

  [
object Object]

  js
> obj.run()

  running

 

  現(xiàn)在我們構(gòu)造一個JavaScript對象,實現(xiàn)Runnable接口。并將該對象作為參數(shù),構(gòu)造一個新的線程,并啟動該線程。

  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的先后順序是隨機的,取決于線程的調(diào)度策略。

  從后端的處理流程來講,Rhino首先為Runnable接口的實現(xiàn)類生成Java字節(jié)碼文件。然后調(diào)用JavaScript對象定義的Run方法。

  4. Rhino如何創(chuàng)建Java 數(shù)組

  Rhino使用Java的發(fā)射機制生成數(shù)組。下面是生成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關(guān)鍵字處理異常。

  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

 


  【IT168 專稿】6. Rhino如何調(diào)用js文件

  當然,除了在命令行的方式,我們還可以使用操縱JavaScript文件。下面是一段JavaScript代碼,主要目的是判斷該數(shù)是否為質(zhì)數(shù)。代碼如下:

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。然后我們需要調(diào)用load方法加載該腳本。最后,我們可以調(diào)用isPrime方法來判斷是否為質(zhì)數(shù)。

 

  js> load("C:/isPrime.js")

  js
> isPrime(33);

  
false

  js
> isPrime(31)

  
true

  需要注意的是,注意:文件分隔符需要調(diào)整,是“/”而不是“\”。

  上述部分示例可以參見Rhino官方網(wǎng)站https://developer.mozilla.org/en/Scripting_Java。另外examples目錄下很多例子都值得參考與學(xué)習(xí)。

  剛才使用JavaScript操縱Java對象。接下來我們看看如何使用Java程序訪問JavaScript

  Java對象操縱JavaScript

  下面是一段Java代碼,用來運行數(shù)學(xué)表達式。代碼如下:

  

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, null1null);

  System.out.println(str 
+ "=" + Context.toNumber(result));

  } finally {

  Context.exit();

  }

  }

  }

 

  運行Java com.example.Test,輸出結(jié)果如下:

  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運行時的速度,進而實現(xiàn)與V8的競爭。而Oracle在對JVM上的JavaScript改進與優(yōu)化,我們有理由期待,在未來,新一代JavaScript運行時Nashorn的速度將會得到極大的提升。

  參考資料:http://www.mozilla.org/rhino/

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多