
<h1>Java Support Overview</h1>

<p>JRuby has a new interface for loading and using Java classes as of
version 0.5.2.</p>

<h2>Goals</h2>

<p>To make Java classes as easy to use as possible they should ideally
behave just like Ruby classes. In most cases this works flawlessly,
but when compromises have to be made they are not always right for
every purpose. The old Java support solved the first problem, but
didn't offer a solution when more control was needed.
The design goals for the new Java support was to keep the simplicity
of the old java support, but allow for low-level access with full
control whenever needed.</p>

<h2>Design</h2>

Java support was split into two halves, "low-level" and
"high-level". The low-level is implemented in Java and provides a thin
wrapper over Java's reflection classes (java.lang.reflection.* and
java.lang.Class). The high-level is built on top of this, implemented
entirely in Ruby.

<h2>Low-level</h2>

<p>It is probably easier to understand this API if you are familiar with
the Java Reflection API.</p>

<p>All Java objects used in Ruby code are wrapped in JavaObject
instances. On their own they can't do very much. But used together
with instances of JavaMethod, a method call can be made:</p>

<pre class="code">
java_method.invoke(java_object, arg1, arg2)
</pre>

<p>JavaClass, JavaMethod and JavaField are used to get information about
Java classes. Which methods and fields do they have, what interfaces
do they implement, are they final, static or public?
Everything that is possible to do in Java itself should be possible to
do with the low-level API, albeit in an awkward way.</p>

<h2>High-level</h2>

<p>A raw JavaObject is not very useful for scripting. So instead we
use a JavaProxy, which has methods corresponding to the real Java
methods on the JavaObject. Every call to one of those methods is
implemented as a call though the low-level 'invoke' method. When using
the high-level API you will rarely come across a JavaObject, since every
returned value is automatically wrapped in a JavaProxy.</p>

<p>The only thing the script developer has to do is to load the
high-level support and include the wanted Java packages into a Ruby
class or module:</p>

<pre class="code">
require 'java'                 # Load the high-level Java support

module Foo
  include_package 'java.util'  # Classes in java.util will be
                               # available in this module

  r = Random.new               # Create instance of java.util.Random

  puts r.nextInt               # Write a random integer to output

end
</pre>

As of ruby 0.8, it is possible to rewrite the following exmaple as follows:

<pre class="code">
require 'java'

include_class 'java.util.Random'

r = Random.new

puts r.nextInt
</pre>

<p>In both examples the 'int' returned from the Java method nextInt() is 
automatically converted into a Fixnum. These conversions are automatically 
done for numbers, booleans and strings, both to and from Java. However, it 
does *not* convert collection and array types like the old Java support
did.</p>

<p>Unlike the first example, the second example is importing Random directly
into the top-level (whereas, the first requires you import a whole package
into a non-top-level module)..</p>

Copyright (c) Anders Bengtsson 2002
Copyright (c) Thomas E Enebo 2005

