JavaScript 向 Java 的通訊

 

JavaScript 向 Java 的通訊

當你參考 Java 的包裝 (package) 或類別的時候,或者運用 Java 物件或陣列的時候,你就使用了獨特的 LiveConnect 物件。所有 JavaScript 向 Java 的存取動作都會使用到這個物件,有關這些的摘要已列在下表中。

物件 說明
JavaArray 已包裝的 Java 陣列,會在 JavaScript 中的代碼存取。
JavaClass JavaScript 對 Java 類別的參考。
JavaObject 已包裝的 Java 物件,會在 JavaScript 中的代碼存取。
JavaPackage JavaScript 對 Java 包裝(package)的參考。

表 9.1 LiveConnect 物件


附註: 因為 Java 是強類型的語言,而 JavaScript 是弱類型,當你使用 LiveConnect 的時候,JavaScript 執行時期引撉會針對其他的語言把參數值轉換成適當的資料類型。參閱 資料類型的轉換 以取得完整資訊。

某方面來看,LiveConnect 物件是一種隱形的存在,因為你會以相當直觀的方法與 Java 互動。例如,你可以使用 new 運算子和 Java 的建構子建立 Java 的 String 物件,並把這個物件代入給 JavaScript 的變數 myString,如下︰

var myString = new java.lang.String("Hello world")

在這個例子中,變數 myString 就是 JavaObject,因為他握有 Java 物件 String 的實體。就如同 JavaObjectmyString 也可以存取 java.lang.String 公開的實體方法,以及他的親類別 java.lang.Object。這些 Java 方法就在 JavaScript 中作為 JavaObject 的方法來使用,你可以按如下方式呼叫︰

myString.length() // 返回 11

可在 JavaClass 物件上直接呼叫靜態成員。

alert(java.lang.Integer.MAX_VALUE); // 警報 2147483647

Packages 物件

如果有某一個 Java 類別並不屬於 javasunnetscape 包裝,你就使用到 Packages 來存取那個類別。例如,假設 Redwood 公司使用了稱為 redwood 的 Java 包裝用來容納各種該公司所實裝的 Java 類別。若要建立 redwood 裡的 HelloWorld 類別的實體,你可如下存取類別的建構子︰

var red = new Packages.redwood.HelloWorld()

你也可以存取位在預設包裝中的類別(也就是無須明確表示包裝名稱的類別)。例如,如果 HelloWorld 類別正好位在 CLASSPATH 裡而不在包裝裡,你可如下來做存取︰

var red = new Packages.HelloWorld()

LiveConnect 的 javasunnetscape 物件針對常用的 Java 包裝提供簡寫。例如,你可如下使用︰

var myString = new java.lang.String("Hello world")

以取代較長的形式︰

var myString = new Packages.java.lang.String("Hello world")

Java 陣列的運用

當你在 JavaScript 中使用任意的 Java 方法建立陣列並加以參照的時候,你已經使用到 JavaArray。例如,下面的代碼以 10 個類型為 int 的元素建立了 JavaArray x

x = java.lang.reflect.Array.newInstance(java.lang.Integer, 10)

就如同 JavaScript Array 物件,JavaArray 也有可返回元素數目的 length 屬性。有別於 Array.lengthJavaArray.length 是唯讀的屬性,因為 Java 陣列中的元素數目在建立的時候就已經固定住了。

包裝和類別的參考

在 JavaScript 中建立 JavaPackage 和 JavaClass 物件,就能簡單的參照 Java 包裝和類別。在稍早的 Redwood 公司的例子中,參考 Packages.redwood 的就是 JavaPackage 物件。同樣的,參考諸如 java.lang.String 的也是 JavaClass 物件。

大多數時候,你不必為 JavaPackageJavaClass 物件而擔心—你只需使用 Java 包裝和類別來做事,LiveConnect 會默默的建立這些物件。在此有一個 LiveConnect 載入類別時會失敗的例子,而且需要你如下手工載入︰

var Widgetry = java.lang.Thread.currentThread().getContextClassLoader().loadClass("org.mywidgets.Widgetry");

在 JavaScript 1.3 及早期版本中,當你把 JavaClass 物件傳給 Java 方法作為參數的時候,這些物件並不會自動轉換成 java.lang.Class 的實體—你必須建立 java.lang.Class 實體的包裝器 (wrapper)。在下面的範例中,forName 方法建立了包裝器物件 theClass,然後把他傳給 newInstance 方法來建立陣列。

// JavaScript 1.3
theClass = java.lang.Class.forName("java.lang.String")
theArray = java.lang.reflect.Array.newInstance(theClass, 5)

在 JavaScript 1.4 以後的版本中,你可以直接把 JavaClass 物件傳送給方法,就如同下面的例子︰

// JavaScript 1.4
theArray = java.lang.reflect.Array.newInstance(java.lang.String, 5)

char 類型的參數

在 JavaScript 1.4 和以後的版本中,你可以把單一字元的字串傳給所需參數的類型為 char 的 Java 方法。例如,你可以把字串 "H" 傳給 Character 建構子如下︰

c = new java.lang.Character("H")

在 JavaScript 1.3 和早期版本中,你就必須給這些方法傳入與字元的 Unicode 值相對應的整數。例如,下面的代碼會把值 "H" 代入給變數 c

c = new java.lang.Character(72)

在 JavaScript 中處理 Java 的例外

當 Java 代碼在執行時期失敗的時候,他就會丟出例外。如果你的 JavaScript 代碼存取 Java 的資料成員或方法並且失敗的時候,Java 的例外會被傳送到 JavaScript 以供你處理。從 JavaScript 1.4 開始,你可以在 try...catch 區塊裡捕捉這些例外。(雖然這個機能連同其他部分已在 Gecko 1.9 中失效 (詳見 bug 391642),不再於 Mozilla 內部維護 Mozilla 特有的 LiveConnect 代碼,但已在 Java 6 更新的 11 和 12 的建置版本中,在 Mozilla 實裝的通用 (跨瀏覽器) NPAPI 插件的代碼中提供對 Java 的支援,並修復此問題。)

例如,假設你使用 Java 的 forName 方法把 Java 類別的名稱代給稱為 theClass 的變數。如果你傳給他的值並不是 Java 類別的名稱,forName 方法就會丟出例外。把 forName 的代入語句放在 try 區塊以處理例外,如下︰

function getClass(javaClassName) {
   try {
      var theClass = java.lang.Class.forName(javaClassName);
   } catch (e) {
      return ("The Java exception is " + e);
   }
   return theClass
}

在這個例子中,如果 javaClassName 可求出合理的類別名稱,例如 "java.lang.String",代入就會成功。如果 javaClassName 求出無效的類別名稱,例如 "String",getClass 函數會捕捉例外,並返回類似下面的東西︰

The Java exception is java.lang.ClassNotFoundException: String

若要針對例外的類型做特別的處理,可以使用 instanceof 運算子︰

try {
  // ...
} catch (e) {
  if (e instanceof java.io.FileNotFound) {
     // handling for FileNotFound
  } else {
    throw e;
  }
}

參閱 例外處理語法 以取得更多有關於 JavaScript 例外的資訊。

文件標籤與貢獻者

 此頁面的貢獻者: teoli, happysadman
 最近更新: teoli,