|
フリーの ECMAScript インタプリタ。
Java で記述された JavaScript インタプリタ。 |
JavaAccess 拡張は、対話式インタプリタでは必ず読み込まれるもので、
CLASSPATH から利用可能なあらゆる Java クラスにユーザーが直接に
アクセスできるようにします。Netscape の "Packages" 機能と
ほぼ互換です。example ディレクトリには JavaAccess の様々な例が
あります。より詳細については、
Netscape の JavaScript リファレンスがちょうどいい情報源になります。
Java プログラムから ECMAScript にアクセスする方法については、
Java ライブラリの項を参照して下さい。
ECMAScript で Java のイベントハンドラを生成する方法については、
イベントハンドラの項を参照して下さい。
JavaAccess 拡張で定義されているオブジェクト
この拡張には 5 つの新しいオブジェクトが含まれます。
-
Packages
-
すべての Java パッケージのルートを表す JavaPackages オブジェクト。
Packages オブジェクトのプロパティがアクセスされると、
対応する JavaPackages オブジェクトが生成されます。
例えば "Packages.EDU.nowhereUni" とすると、
"EDU.nowhereUni" に対する JavaPackages が生成されます。
JavaPackages はただの名前接頭辞で、必ずしも実際のパッケージに
一致するわけではありません (パッケージ内のクラスが使われた時点では
そのパッケージが必ず実際のものになります)。
-
したがって次のようにパッケージを省略するのは簡単です。
tools = Packages.EDU.puddingtonUni.tools
-
さらに、Packages はクラスローダの作成にも使用でき、
ディレクトリのルートや Jar ファイルからクラスを読み込むのに利用できます。
このローダを作成するには、ディレクトリや Jar ファイルの名前を指定して、
Packages を関数として呼び出します。例えば、
new Packages("java/graphics/classes").graphics.line
-
とすると、java/graphics/classes のサブディレクトリ内の
クラス 'graphics.line' を参照します。
同様に Packages("C:/library/tools.jar") とすれば指定した tools という
Jar ファイルからクラスを読み込むための新しいルートを作成できます。
-
Packages オブジェクトが with ステートメントの式である場合には
パッケージを生成することはできませんので、
必要なパッケージは with ステートメントの前に
生成しておいて下さい!
-
Beans
-
すべての JavaBeans のルートを表す JavaBeans オブジェクトです。
Beans オブジェクトのプロパティにアクセスすると、
対応する JavaBeans オブジェクトが生成されます。
例えば、"Beans.java.awt.Button" は AWT のボタンを Bean として
扱ったものを示します。Jar ファイルやディレクトリのルートを指定して Beans を
関数として呼び出せば、Beans の新しいルートが作成できます。例えば、
JugglerJar = Beans(bdkHome+"juggler.jar")
-
すると、'new JugglerJar.sunw.demo.juggler.Juggler()' のように、
Beans のルートから相対指定して Bean を生成することができます。
Bean を manifest つきの Jar ファイルから読み込んだ場合でも、
Beans は指定されたクラスが Bean として宣言されているかを検査せずに
そのクラスをインスタンス化しようとします。
-
Bean として宣言されていた場合は、対応する BeanInfo (Beans に
関する Sun のドキュメンテーションを参照) で記述されているプロパティやメソッド
のみがアクセスできます。Bean のプロパティは ECMAScript のプロパティとして
アクセスすることができます (FESI は適切な getter や setter ルーチンを
使い、たとえ public でもフィールドには直接アクセスしません)。
-
java
-
Packages.java と同等で、Java 言語の機能により簡単にアクセスする
ためのものです。
-
javaTypeOf
-
値が Java のメソッドに渡された場合に、生成された Java オブジェクトのクラス名を
返す関数です。オーバーロードされた関数へのアクセスをデバッグするのに
便利です。ECMAScript を Java オブジェクトとしてパッケージするのにちょうどいい
型が見つからない場合はクラス JSWrapper が使用されるので、
ECMAScript のビルトインオブジェクトにこの関数を使うと JSWrapper が
返されます。ECMAScript の値は、それを含む最小の型に単純に変換されます
(1234 なら java.lang.Short)。
-
loadExtension
-
ECMAScript の拡張をプログラムから読み込む関数で、
loadExtension("FESI.Extensions.FileIO") のように
クラス名を引数に与えます。すでに読み込まれている拡張を再読込みしても
なにもおきません。
インタプリタのコマンド @describe は、Java オブジェクトの特性を
調べるのに非常に便利です。そのオブジェクトのクラス、メソッド、フィールドが
一覧表示され、オブジェクトが Bean として使われている場合はプロパティも
表示されます。
Java ないし CORBA オブジェクトのプロパティやフィールド
へのアクセス
Packages 機構によって生成されたり Java 関数から受け取ったりした
オブジェクト (Java 関数から Java オブジェクトとして受け取った CORBA オブジェクト
も含みます) のプロパティやフィールドへアクセスするのには以下の機構が
使われます。
-
最初に同じ名前の public な Java フィールドが探されます。見つかれば、
直接それにアクセスします (setter ないし getter 関数は無視されます)。
-
名前が "on" で始まるフィールドは特別に扱われます。オブジェクト内に
存在していなければ、イベントハンドラ設置の要求と解釈されます
(詳しくはイベント処理のページを参照して下さい)。
-
フィールドが見つからないか public でない場合は、
Bean のイントロスペクションを使ってプロパティを検索します。
イントロスペクションで見つかれば、その getter ないし setter ルーチンが
使われます。
-
最後の望みとして、プロパティと同じ名前のルーチンを setter (void で
同じ型の引数を 1 つとるもの) ないし getter (引数をとらず値を返すもの) として
検索します。この最後のメソッドは、Java からアクセスする CORBA オブジェクトと
互換性があります。
(Bean 生成メカニズムを使って) Bean として宣言されているオブジェクトのプロパティ
は、Bean のイントロスペクションでの検索のみを行ないます。
当然、必ず直接に setter ないし getter ルーチンを呼ぶことができます。
Java オブジェクトの生成
一度 JavaAccess パッケージが読み込まれると、新しい Java オブジェクトを
生成できるようになります。例を挙げます。
cal = new java.util.GregorianCalendar();
Java オブジェクトは多くの場合 ECMAScript のネイティブオブジェクトとして
呼び出されます。文字列、日付、数値は ECMAScript と Java の間で自動的に
変換されます。互換性のないオブジェクトはラップされます。つまり、
Java オブジェクト (Calendar など) は ECMAScript のラッパーオブジェクトによって
表されます。このラッパーオブジェクトがネイティブ関数に対処し
プロパティにアクセスするのです。ラッパーが Java のルーチンに戻されると
ラップされていた (Java ネイティブの) オブジェクトがその値として
使用されます。オーバーロードされている関数の場合は、ラッパーは
適切なインスタンスを見つけようとし、必要な場合は数値を大きい型にしたり
単一の文字からなる String を Character に変換したりすることもあります。
Java ルーチンから返された配列は、配列としてラップされ配列として操作されます。
ラップされている配列が Java のルーチンに戻されると、配列はラップ解除されます。
配列のすべての要素が対象となる配列のコンポーネント型に変換できるのであれば、
Java の配列が必要な場面では必ず ECMAScript の Array が利用できます。
その場合は配列をコピーしたものが引数として使われるため、非常に大きな配列では
時間がかかることがあります。配列を Java と ECMAScipt で共有しなければならない
場合は、その配列は Java 側で生成しなければなりません。
Java のクラスやオブジェクトの名前が ECMAScript の予約語と重なっている場合は
動的な索引記法を使わなくなければなりません。例えば次の例を見て下さい。
java.lang.System["in"]
'java.lang.System.in' だと文法エラーを起こすので、
'in' は ECMAScript のキーワードです。
Enumeration を使う
"for in" 構文で Java の Enumeration を直接使うことができます。
例を挙げます。
// プロパティの取得
properties = java.lang.System.getProperties();
// Java の Enumeration を使って一覧表示します
for (key in properties.keys()) {
value = properties.get(key);
writeln ("プロパティ '" , key, " = '", value, "'");
}
コンストラクタを関数として使う
Java のクラス名が関数として使われると、対応するコンストラクタがあれば
呼び出されます - 例を挙げます。
cal=java.util.GregorianCalendar()
要素の値には違いがあります。第 1 に、ECMAScipt の型に変換できる値は
自動的に変換されます。例えば str=java.lang.String("Hello") は、
Java の String をラップしたものではなく ECMAScript の文字列を
生成します。しかし、基本型に new をつけて使うと、
代わりに Java の String が返されます。
ラッパーは最初に使った時点で ECMAScript の文字列に変換されることになりますが、
これは複雑なオーバーロードの衝突を防ぐために変数の型を強制するのには
好都合です。例えば javaObj.append(new java.lang.Long(23)) とすれば、
append 関数のうち (Double などではなく) Long を
引数としている ものを探すように ECMAScript に指示することができます。
FESI でイベント処理ルーチンを定義することができます。
詳しくは FESI のイベント処理のページを参照して
ください。
制限事項
索引化されている Bean のプロパティは、配列全体が一度にアクセスおよび取得できる
こと以外は現在ではサポートされていません。
Bean やイベント処理の情報はオブジェクトのラッパーに保持されます。
FESI が Bean や Java オブジェクトを生成したり受け取ったりし、
FESI から Java ルーチンに渡されてから FESI に (例えば
戻り値として) 返された場合は、新しいラッパを受け取ります。これは
とくにそういったオブジェクトの同等性に関して多少の混乱をきたします。
FESI 内の Bean や Java オブジェクトのオリジナルの参照を常に使うこと
をお勧めします。
ルーチンの選択はオーバーロードの解決のために発見的な方法に基づいています。
呼ばれたルーチンが予想されたものでなかった場合には
インタプリタで @debugJavaAccess を使う必要があるかもしれません。
Java と ECMAScript の型づけではモデルが異なるため、必ず一意な変換が行なえる
わけではありません。実際にはそういう例は稀であり、必要な場合には
ラッパールーチンや拡張を作成することができます。
メインページに戻る
最終更新日 (原文): 1999 年 3 月 6 日
(翻訳): 1999 年 4 月 1 日