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としましょう。