C言語のライブラリをRubyから使おうとすると、その間をつなぐグルーコードに悩まされることに、往々にしてなりますが、JRubyからJavaのライブラリを呼ぶのは、それよりは楽です。
なお、この記事は適宜追加していく予定です。
まずはrequire
まずは、require 'java'
と書くと、JRubyのJavaサポートが発動します。また、CRubyでネイティブの.so
をrequire
できるのと同様に、JRubyでは.jar
ファイルをrequire
することもできます(なお、JRuby向けなjarをrequire
すればそのままJRuby側に現れますが、組み込みのJavaクラスと同じようなやり方でアクセスするために、ふつうのjarをrequire
することも可能です)。
Javaのクラスにアクセスするための手法
Javaのクラスは、java.lang.StringBuilder
やorg.apache.commons.collections4.CollectionUtils
というように、パッケージで区分されています。これをJRubyの世界で表現するには、いくつかの方法があります。
まず1つは、パッケージ名をドット区切りからキャメルケースにして、Java::
以下のモジュール名として、それをクラスにするという方法です。上の2つであれば、Java::JavaLang::StringBuilder
、Java::OrgApacheCommonsCollections4::CollectionUtils
となります。p
などで見たクラス名もこれになっています。
次に、トップレベルの定数からドット区切りのまま参照する、という方法があります。Java::Java.lang.StringBuilder
やJava::Org.apache.commons.collections4.CollectionUtils
というような書き方になります。
さらに、require 'java'
とした時点で、Ruby側のカーネルメソッド(puts
のような、どこでも書けるメソッド)としてjava
、javax
、org
、com
が用意されます。これを使うことで、java.lang.StringBuilder
やorg.apache.commons.collections4.CollectionUtils
が、そのままRuby側で使えるようになります。ただし、これらを変数で書き潰さないように注意が必要かもしれません。
メソッドへのアクセス
JavaもRubyもオブジェクト指向の言語なので、メソッド呼び出しは普通に行えます。なお、new
はRuby的に、クラスメソッドとなっています。
Ruby的に書く
メソッドの書き方が、Rubyではスネークケース(アンダーバー区切り)ですが、Javaではキャメルケース(大文字区切り)という慣習になっています。JRubyでは、obj.foo_bar_baz
をobj.fooBarBaz
のように変換してくれます(もちろん、Javaの名前で書いても構いません)。
また、JavaBean的なgetXXX()
、setXXX()
を、Rubyのプロパティとしてアクセスができるほか、isHoge()
のようなメソッドはhoge?
としても使えます。
java_send
Javaはメソッドをオーバーロードできますが、Rubyで型がうまく表現できない、あるいはJavaでのメソッドがinitialize
という名前で、Rubyのコンストラクタと干渉するので呼べない、というような場合には、java_send
というメソッドを使えます。オーバーロードに対応するという性質上、メソッド名だけでなくシグネチャも指定する必要があります。
注意が必要な引数・返り値
Javaのクラスを渡したい
たまに、JavaでClassName.class
のような引数を渡す場面がありますが、JRubyでこう書いてしまうと、Ruby側のクラスオブジェクトが渡ってしまって、うまく動きません。ClassName.java_class
としましょう。
配列が返り値の場合
配列が返り値の場合、Javaネイティブな配列が返ってきてしまいます。Rubyで使うには.to_a
としましょう。