2009-04-19
JavaScript(Rhino)からJavaのクラスにアクセスする
Java, JavaScript, Ubuntu | |
以下のサイトを参照してやってみる。
RhinoからJavaのクラスにアクセスするのはすごく簡単。一番簡単に使う方法は以下の様に、パッケージ名まで含めたクラスを指定して使うだけ。
js> list = new java.util.ArrayList(); [] js> list.add(1);list.add(2);list.add(3); true js> list [1.0, 2.0, 3.0]
ま、これじゃ面倒なのでインポートすることも出来る。
js> importPackage(java.util); js> list = new ArrayList(); [] js> list.add(1);list.add(2);list.add(3); true js> list [1.0, 2.0, 3.0]
ほうほう。今までJavaScriptからJava使うってやったことなかったけど思った以上に簡単だねー。
ファイルの読み込み
js> importPackage(java.io); br = new BufferedReader(new FileReader("/home/hironemu/text.txt")); while(line = br.readLine()) {print(line)} js> br.close();
こんな感じで普通にJavaのクラスを使って実現出来る。
Javaのインターフェースを実装する
例としてRunnableインターフェースを実装するのがあったので同じようにやってみる。因みにJavaでRunnableインターフェースを実装して、スレッドを実行するのは以下のようになる。
Runnable r = new Runnable() { @Override public void run() { System.out.println("running.."); } }; Thread t = new Thread(r); t.start();
JavaScriptではまず、Runnableの実装をハッシュ作る↓
js> importPackage(java.lang); js> obj = {run: function () {print("running...")}}
objはハッシュです。この場合キーには「run」、値には「function() {print("running...")}」が定義されている状態。ここがJavaScriptの面白いところで値に関数を入れることが出来る。そして、このキー呼ぶときに「()」をつけると関数として実行してくれる。
js> obj.run() running...
こいつを、Runnableインターフェースの実装として使う。
js> r = new Runnable(obj);
adapter1@1bac748
お。このadapterってなんだろね。JavaとJavaScriptの間にある何かとか?
次にThreadクラスを作るときに引数として「r」を渡してやればOK。
js> t = new Thread(r); Thread[Thread-0,5,main] js> t.start(); running...
これを簡略化して以下のようにもかけるらしい。Runnableみたいに実装するメソッドが一つの場合は、そのメソッドの実装だけを渡してあげればいいんだって。ThreadのコンストラクタにはRunnableを引数にとるものがあって、Runnableのメソッドは一つだけって分かってるからあとは自動でやってくれてるってことだろう。だいぶ簡単にかけるね。
js> t = Thread(function() {print("running...")}); Thread[Thread-1,5,main] js> t.start(); running...
あり、newを書き忘れたけど実行できたね。これはなんでやろ。
Javaの配列を使う
RhinoはJavaの配列を使うための構文を用意していないらしい。なので、リフレクションを使ってJavaの配列をnewする。これははじめてみたなー。
js> array = java.lang.reflect.Array.newInstance(java.lang.String, 5); js> array.length 5 js> array[0] = "first"; first js> array[1] = "second"; second js> for (i in array) {print(array[i])} first second null null null
おっと。JavaScriptのfor in構文は値を返すんじゃなくて、キーを返すみたいだね。
プリミティブな配列をつくる場合はnewInstanceの初めの引数に、TYPEを渡すらしい。(charの例はあるので、intの例を。
js> intArray = java.lang.reflect.Array.newInstance(java.lang.Integer.TYPE, 2); [I@f72617 js> intArray[0] = 1; 1 js> intArray[1] = 2; 2
js> intArray[0] = "string"; js: "<stdin>", line 66: Cannot convert string to java.lang.Integer at <stdin>:66
お。コンバート出来ませんってことは、コンバートしてくれそうなやつだと、、
js> intArray[0] = "10"; 10
ほほう。intに変換出来る文字列だと勝手に変換してくれるんだ。べんりー。こんなのは。
js> intArray[0] = "10.02"; 10.02 js> intArray[0] 10
floatっぽい数字を入れてみると、勝手に丸めてくれる。ま、あたりまえか。
JavaScriptの文字列とJavaの文字列
JavaScriptの文字列とJavaの文字列は違う。Javaの文字列はjava.lang.Stringクラスとして定義されているて、JavaScriptの場合は、String.prototypeによって定義されている。なので、以下の様に文字の長さを知るためのメソッドにも違いがある。
js> javaString = new java.lang.String("java"); java js> javaString.length(); // java.lang.Stringのlengthメソッド 4 js> jsString = "JavaScript"; JavaScript js> jsString.length; // String.prototypeに定義されたプロパティlength 10
でも、この2つの違いを吸収するようにRhinoはがんばってくれてるみたい。例えば、JavaのStringを使いたいときにJavaScriptのStringを渡すことができ、上の例の「new java.lang.String("java")」としている部分ではまさにそれをやっている。"java"って文字列はJavaScriptの文字列なんだけど、これをJavaのStringに渡すときに変換してくれてるのだろう。
その他に、java.lang.Stringのクラスに定義されていないメソッドを呼び出そうとすると、JavaScriptのメソッドから探してこようとする。のかな?
js> javaString.slice(0, 2); ja
こんな感じで、java.lang.Stringにsliceってメソッドは定義されてないんだけど、JavaScriptの方には定義されているからそっちを実行してくれるんだね。
あり。逆はダメなのね。
js> jsString.trim(); js: "<stdin>", line 97: uncaught JavaScript runtime exception: TypeError: Cannot find function trim in object JavaScript. at <stdin>:97
- 19 http://www.google.co.jp/search?hl=ja&q=ありの日記&sourceid=navclient-ff&rlz=1B5GGGL_jaJP310JP310&ie=UTF-8&aq=h
- 10 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GFRC_jaJP204JP205&q=ラーメン がっつり
- 9 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=efJ&q="ubuntu+9.04"&as_qdr=w&btnG=検索&lr=lang_ja
- 6 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=com.ubuntu:ja:unofficial&hs=G4X&q=アップグレード+ubuntu+9.04&btnG=検索&lr=
- 5 http://www.google.com/cse?cx=014345598409501589908:mplknj4r1bu&ie=UTF-8&q=aptana+UBUNTU&sa=Search
- 4 http://search.yahoo.co.jp/search?p=ubuntu+9.04&search_x=1&tid=top_ga1_sa&ei=UTF-8&aq=2&oq=ubuntu&pstart=1&fr=top_ga1_sa&b=11&qrw=0
- 4 http://www.google.co.jp/reader/view/
- 4 http://www.google.co.jp/search?q=xubuntu&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:ja:unofficial&client=firefox-a
- 3 http://cgi.5on.biz/data/2009/02/23.shtml
- 3 http://www.google.co.jp/search?hl=ja&q=XUbuntu&btnG=Google+検索&lr=lang_ja&aq=f&oq=
おっしゃるとおり、どんなに嫌でも避けられないことというのは、課長の仕事以外にも世の中にたくさんありますよね。でも、そんな嫌なことを直視していくことが、大人の責任なんじゃないかな、とも思います。
よろしければ、僕のブログにも遊びに来てください。今後とも、よろしくお願いします!
まさか、酒井さん本人からコメントいただけるとは思ってもみなかったのでびっくりです。
>でも、そんな嫌なことを直視していくことが、大人の責任なんじゃないかな、とも思います。
責任。ですね。逃げてるだけだとホントに何にも変わらないし、自分の下の世代にも同じ思いさせるんだろうなと思いました。そうはさせたくないし、また、自分の力で何か改善できるのだとしたら、目をそらしてるわけにはいかないですよね。
負けそうになったらまた、本読み直してみます(笑)
ブログさっそく購読しました。写真きれいですねー。
これからゆっくり読ませていただきますw
http://www.mozilla-japan.org/rhino/scriptjava.html
情報ありがとうございます。
つまり、JavaScriptでJavaの拡張やインターフェースの実装を行うためのライブラリって事ですよね。単一のインターフェースを実装する場合は、JavaAdapterを自ら使わなくてもハッシュオブジェクトを渡すだけで簡単に実装できて、もうちょっと複雑な複数のインターフェースを渡す場合なんかはこのJavaAdapterを使うんですね。
勉強になりましたm(_ _)m