配列の相互変換
Rubyの配列はto_java
メソッドでJavaの配列に変換できます。to_java
メソッドを無引数で呼び出した場合はjava.lang.Object[]
に変換されます。次のような引数を与えて、Java配列の要素型を指定することもできます。
- :boolean
- :byte
- :char
- :short
- :int
- :long
- :float
- :double
- :decimal
- :big_integer
- :object
- :string
現在の実装では、Rubyの配列に不適切な型の要素があっても、かなり強引に型を自動変換します。この振舞は実用的ですが、注意が必要です。逆変換にはto_a
メソッドを使います。
下記のjirbセッションでは、Rubyの文字列からRubyの配列a
を得て、それをJavaのbyte配列bb
に変換してから、to_a
でRubyの配列に逆変換したり、java.lang.String
のコンストラクタに与えてJavaの文字列ss
にしています。
irb(main):021:0> a = "the great ruby".unpack("C*") => [116, 104, 101, 32, 103, 114, 101, 97, 116, 32, 114, 117, 98, 121] irb(main):022:0> bb = a.to_java(:byte) => #<#<Class:01x9104ed>:0x7a07ac @java_object=[B@8de768> irb(main):023:0> bb.to_a => [116, 104, 101, 32, 103, 114, 101, 97, 116, 32, 114, 117, 98, 121] irb(main):024:0> ss = java.lang.String.new(bb) => #<Java::JavaLang::String:0xbbd743 @java_object=the great ruby> irb(main):025:0> ss.to_s => "the great ruby"
独自のJavaライブラリへのアクセス
非標準的なJavaライブラリへJRubyからアクセスするには、require
メソッドにjarファイルの名前を文字列として与えます。標準Javaライブラリのように、モジュールJava
のメソッドとして、そのJavaパッケージを参照できるようになります。ただし、現在の実装では、名前の検索トリガを機能させるためか、jpなどで始まるパッケージへは二重コロン記法Java::
でアクセスする必要があります。include Java
ではアクセスできません。
下記はJavaによるLispインタープリタL2Lisp 5.0のLL.javaのクラスLL
をRuby定数LL
に得て、そのmain(String[] args)
メソッドを呼び出す例です。一時ファイルtf
にLispスクリプトscript
の内容を書き込み、そのパス名tf.path
を配列要素とするJavaのString配列を[tf.path].to_java(:string)
で作成し、そしてそれをJavaのmain
メソッドに渡しています。メソッドの仮引数と型の不一致が起こりますから、to_java(:string)
の:string
は省略できません。
script = ' (princ "1 + 2 = ") (print (+ 1 2)) (princ "100! = ") (print (reduce * (range 1 101))) ' require "tempfile" tf = Tempfile.new("lisp_script") tf.puts(script) tf.close require "../tmp/L2Lisp.jar" LL = Java::jp.co.okisoft.ngo.suzuki611.llsp.LL LL.main([tf.path].to_java(:string))
下記がその実行例です。確かにLispスクリプトが実行されています。
$ jruby ll.rb 1 + 2 = 3 100! = 9332621544394415268169923885626670049071596826438162146859296389521759999 32299156089414639761565182862536979208272237582511852109168640000000000000000000 00000 $
おわりに
ここではJRubyからJavaのクラスを利用する観点でのJRubyの特徴と機能を説明しました。
本稿で述べたほかにも、JRubyはjava.util.Collection
にeach
イテレータを定義し、Enumerable
モジュールをmix-inさせているなど、JavaのクラスをRubyらしく簡潔に使う便宜を提供しています。そういった便宜はRubyの人々が抱く直感に沿って用意されていますから、Rubyに慣れるにつれ、JRuby経由でJavaのクラスもどんどん便利に使えるようになります。
JRubyの実装はまだ完全ではありませんが、いわゆるJavaからRubyへ、というあれかこれかの二者択一ではなく、豊富なライブラリと、飾り気のない簡潔明快な記述という両者の長所を享受する道が、JRubyによって開かれています。
参考資料
- Rubyチュートリアル(沖ソフトウェア)
本稿は上記チュートリアルの第8章をまとめ直したものです。