JRuby 'to_java' by example

Posted in Original Content by David Cavalero - last update: Dec 23, 2023

If you arrive on this page - you were probably following a link. This page was created by David Cavalera, who no longer owns this domain. It is still linked/indexed - so I decided to keep it online You can find David on Twitter/X or LinkedIn

Original version of this page can still be found on the internet archive.

<Original content below:>

One of the JRuby killer features is that we can use Java classes into our Ruby code as they were Ruby classes. This is the foundation for hundred of projects, take your favourite Java library and create a layer to do it more Ruby friendly, Trinidad’s core is completely written in Ruby thanks to this, for example.

JRuby is smart enough to know when we are using a Java class and it converts the call arguments from Ruby to Java objects. But there is always a recurrent question when we work with the Java integration layer, how can we convert a Ruby array to a Java array when it contains other arrays?

Let’s say we have a Java class called ‘Foo’ with a method ‘bar’ that takes a string as an argument:

public class Foo {
    public void bar(String baz) {}
}

JRuby knows how to convert a Ruby string to a Java string, so the code to call this method is pretty straightforward:

Foo.new.bar 'hello'

<End or original content>

Now, let’s say this same method takes an array of string as an argument:


public class Foo {
    public void bar(String[] baz) {}
}

Here the code to call it starts to be tricky. We need to use the method ’to_java’ to convert our Ruby array, mostly because we don’t know what’s inside the array, there are several performance implications to know it so we prefer to do it explicit:

Foo.new.bar ['hello'].to_java

This method can take an optional argument, this is the type of the objects inside the array and by default is ‘:string’. Here comes the key to understand how to use this method properly in any case, when we pass a symbol as argument we are passing an alias for a Java class name, but this method also accepts Java class names directly, so these calls are equivalent:

Foo.new.bar ['hello'].to_java
Foo.new.bar ['hello'].to_java(:string)
Foo.new.bar ['hello'].to_java(java.lang.String)

So now, let’s say our example method takes an array of string arrays as an argument:


public class Foo {
    public void bar(String[][] baz) {}
}

In this case we’ll need to use the Java class name directly, as easy as this:

Foo.new.bar [['hello']].to_java(java.lang.String[])

Knowing this we can work with any array of Java objects but primitives. The syntax for these types is slightly different since they don’t match any Java class name, we’ll need to use ‘Java’ as package name followed by the name of the primitive type itself.

Let’s say our ‘bar’ method takes now an array of boolean arrays as an argument:

public class Foo {
    public void bar(boolean[][] baz) {}
}

The code to call this method will be:

Foo.new.bar [[true, false]].to_java(Java::boolean[])

Finally, as a complete example guide what else but our own tests, the JRuby’s java_integration specs are plenty of useful ones, I recommend you the array the construction specs.

<End or original content>

Other articles