The package rJava provides an easy to use mechanism to call Java objects and methods from R. This page will show you how to build, inspect, and manipulate Java objects without leaving the comfort of R. Particular focus will be paid to GUI objects.

Objects in Java

Java is an object oriented language, meaning that almost everything is an object, and all functions (i.e. methods) are linked to objects. This is in contrast to R, which is primarily a function oriented language.

A class is a template used to create a specific type of object. For example I might have a class called Chair. This class is not an object it's self, but rather contains the recipe for creating a chair. This recipe is called a constructor, and when called creates a Chair object. It can be called many times to create a series of chairs (e.g. this chair, and that chair over there). Each one of these chairs is called an 'instance of' the original Chair class.

Classes can also be specific subtypes of other Classes. For example, our Chair class might be a subtype of the Furniture class, because all Chairs are Furniture. So when we create a new Chair object, it is also a Furniture object.

Functions in Java

Functions are called methods in Java, and are tethered to a specific class. Methods can only be used with objects of their own class. For example, a Cheetah class might have a method run which would make the cat run, but we wouldn't be able to call that method to make a Chair run. methods can be called on subclasses though, so I would be able call a Furniture method on a Chair.

A class can also have methods are called on the class (not an instance), and which don't require an instance to run. These are called 'static methods' and can be called using the class even if no objects have been created by that class. For example, our Cheetah class might have a method getPopulation which would return the number of Cheetahs in the wild (i.e. the number of instances). This method relates to Cheetahs, but doesn't relate to any specific Cheetah, so it is a static method.

Working with Java in R

Hopefully the above sounded very familiar to you. R has an object system similar to Java called S4. Though you don't need to know to much about it, we will be using the S4 object system to work with Java classes and objects.

Getting Started

Lets start by making a JDialog object. JDialog is a class used to make a dialog window, and is a part of the Swing GUI library.

The first thing we need to do is create a variable representing the class. This can be done with the J function, which takes as an argument the class location, and returns a reference to that location (an S4 object of class jclassName). JDialog is located in the javax.swing Java package, so we simply need to call.

> JDialog <- J("javax.swing.JDialog")
> print(JDialog)
[1] "Java-Class-Name: javax.swing.JDialog"

Now that we have a reference to the JDialog class, we can a new object by calling the new function. new takes as its first argument a jclassName (e.g. JDialog), and any further arguments are passed to the JDialog constructor.

> myDialog <- new(JDialog)

myDialog is now a reference (of S4 class jobjRef) to an instance of JDialog. We don't see anything yet, because we have not made the dialog visible. There is a JDialog method called setVisible which we can use to make the dialog visible. Set visible takes a boolean (true/false) as a parameter. rJava transparently takes care of the conversion between R logical and Java boolean. We will go into conversions later on.

> myDialog$setVisible(TRUE)

You should now see a small empty dialog window.

looking up constructors and methods

"But wait" you say! This all seems sort of magical.

  1. How did we know that there was a class called javax.swing.JDialog?
  2. How did we know that there was a constructor that took no arguments?
  3. How did we know there was a method called setVisible

Well, number 1 is sort of hard. Java is a big language, with lots of libraries and packages. If you are looking for something in plain Java, you can start by looking through the Java API JavaDocs. For things related to JGR, rJava and Deducer, you can look through the nightly generated Java docs.

Numbers 2 and 3 are easier to answer. we can list the available constructors with the .jconstructors function.

> .jconstructors(JDialog)
 [1] "public javax.swing.JDialog(java.awt.Frame) throws java.awt.HeadlessException"                                                         
 [2] "public javax.swing.JDialog(java.awt.Frame,boolean) throws java.awt.HeadlessException"                                                 
 [3] "public javax.swing.JDialog(java.awt.Frame,java.lang.String) throws java.awt.HeadlessException"                                        
 [4] "public javax.swing.JDialog(java.awt.Frame,java.lang.String,boolean) throws java.awt.HeadlessException"                                
 [5] "public javax.swing.JDialog(java.awt.Frame,java.lang.String,boolean,java.awt.GraphicsConfiguration)"                                   
 [6] "public javax.swing.JDialog() throws java.awt.HeadlessException"                                                                       
 [7] "public javax.swing.JDialog(java.awt.Dialog,boolean) throws java.awt.HeadlessException"                                                
 [8] "public javax.swing.JDialog(java.awt.Dialog,java.lang.String) throws java.awt.HeadlessException"                                       
 [9] "public javax.swing.JDialog(java.awt.Dialog,java.lang.String,boolean) throws java.awt.HeadlessException"                               
[10] "public javax.swing.JDialog(java.awt.Dialog,java.lang.String,boolean,java.awt.GraphicsConfiguration) throws java.awt.HeadlessException"
[11] "public javax.swing.JDialog(java.awt.Dialog) throws java.awt.HeadlessException"  

We can see that previously we called constructor number 6, which takes no arguments. Additionally a JDialog can be created with parameters representing a parent window (Dialog or Frame), a boolean representing whether the dialog is modal (blocking), and/or a String title. It can also take a graphics configuration, but it is rare that you would ever want to do that. So any of the follow commands can make a JDialog:

> JFrame <- J("javax.swing.JFrame")
> aFrame <- new(JFrame)
> anotherDialog <- new(JDialog,aFrame)
> anotherDialog <- new(JDialog,aFrame,TRUE)
> anotherDialog <- new(JDialog,aFrame,"title")
> anotherDialog <- new(JDialog,aFrame,"title",FALSE)
> anotherDialog <- new(JDialog)
> anotherDialog <- new(JDialog,myDialog)
> anotherDialog <- new(JDialog,myDialog,"title")
> anotherDialog <- new(JDialog,myDialog,"title",TRUE)

To look up what methods are available we use the .jmethods function.

> .jmethods(myDialog)
  [1] "public void javax.swing.JDialog.remove(java.awt.Component)"                                                                                 
  [2] "public void javax.swing.JDialog.update(java.awt.Graphics)"                                                                                  
  [3] "public javax.accessibility.AccessibleContext javax.swing.JDialog.getAccessibleContext()"                                                    
  [4] "public void javax.swing.JDialog.setLayout(java.awt.LayoutManager)"                                                                          
  [5] "public javax.swing.JRootPane javax.swing.JDialog.getRootPane()"                                                                             
  [6] "public void javax.swing.JDialog.setContentPane(java.awt.Container)"                                                                         
  [7] "public java.awt.Container javax.swing.JDialog.getContentPane()"                                                                             
  [8] "public void javax.swing.JDialog.setLayeredPane(javax.swing.JLayeredPane)"                                                                   
  [9] "public javax.swing.JLayeredPane javax.swing.JDialog.getLayeredPane()"                                                                       
 [10] "public void javax.swing.JDialog.setGlassPane(java.awt.Component)"                                                                           
 [11] "public java.awt.Component javax.swing.JDialog.getGlassPane()"                                                                               
 [12] "public void javax.swing.JDialog.setDefaultCloseOperation(int)"                                                                              
 [13] "public int javax.swing.JDialog.getDefaultCloseOperation()"                                                                                  
 [14] "public void javax.swing.JDialog.setJMenuBar(javax.swing.JMenuBar)"                                                                          
 [15] "public javax.swing.JMenuBar javax.swing.JDialog.getJMenuBar()"                                                                              
 [16] "public static void javax.swing.JDialog.setDefaultLookAndFeelDecorated(boolean)"                                                             
 [17] "public static boolean javax.swing.JDialog.isDefaultLookAndFeelDecorated()"    

The first 17 of 297 methods are displayed above.

We can also view the publicly accessible fields of an object.

> .jfields(myDialog)
 [1] "public static final int javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE"
 [2] "public static final int javax.swing.WindowConstants.HIDE_ON_CLOSE"      
 [3] "public static final int javax.swing.WindowConstants.DISPOSE_ON_CLOSE"   
 [4] "public static final int javax.swing.WindowConstants.EXIT_ON_CLOSE"      
 [5] "public static final float java.awt.Component.TOP_ALIGNMENT"             
 [6] "public static final float java.awt.Component.CENTER_ALIGNMENT"          
 [7] "public static final float java.awt.Component.BOTTOM_ALIGNMENT"          
 [8] "public static final float java.awt.Component.LEFT_ALIGNMENT"            
 [9] "public static final float java.awt.Component.RIGHT_ALIGNMENT"           
[10] "public static final int java.awt.image.ImageObserver.WIDTH"             
[11] "public static final int java.awt.image.ImageObserver.HEIGHT"            
[12] "public static final int java.awt.image.ImageObserver.PROPERTIES"        
[13] "public static final int java.awt.image.ImageObserver.SOMEBITS"          
[14] "public static final int java.awt.image.ImageObserver.FRAMEBITS"         
[15] "public static final int java.awt.image.ImageObserver.ALLBITS"           
[16] "public static final int java.awt.image.ImageObserver.ERROR"             
[17] "public static final int java.awt.image.ImageObserver.ABORT" 

Calling methods

We have already seen how to call the setVisible method on out JDialog. Calling other functions is similar. Our Dialog is pretty small right now. In fact, its size is 0. Lets give it some length and width, as well as a title.

> myDialog <- new(JDialog)
> myDialog$setTitle("cool dialog")
> myDialog$setSize(200L,500L)
> JLabel <- J("javax.swing.JLabel")
> label <- new(JLabel,"Hi there, I'm a label")
> myDialog$add(label)
[1] "Java-Object{javax.swing.JLabel[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Hi there, I'm a label,verticalAlignment=CENTER,verticalTextPosition=CENTER]}"
> myDialog$setVisible(TRUE)
> myDialog$isVisible()
[1] TRUE

You should now see a window 200 pixels wide and 500 pixels long titled "cool dialog." We've also added a text label to the content of the window. Notice that we used 200L for the argument to setSize. This is because the L in R indicates that the number is an integer. Otherwise it would be numeric, which would then be converted to a Java double which the method doesn't understand.

Static methods can be called either on the class or an object, though it is recommended that the class be used.

> JDialog$isDefaultLookAndFeelDecorated()

Fields (variables specific to a particular Java class or object) can also be accessed in a natural way.

[1] 3

Constructor and method argument conversion

You may have noticed that we didn't actually pass any Frames or Dialogs to the constructor in the .jconstructors example above. Rather we gave it JFrames and JDialogs. This is okay because they are subclasses of Frame and Dialog. We can check this using the instanceof operator

> myDialog %instanceof% J("java.awt.Dialog")
[1] TRUE
> aFrame %instanceof% J("java.awt.Frame")
[1] TRUE

rJava automatically takes care of the class conversions (called casting) without any need for you to worry about it. Indeed, it works the other way too. If a java method's signature says that it returns an object of class Frame, but the object is actually a JFrame, it is automatically promoted to a JFrame and can be used as such. In some ways this could be considered an improvement on Java which normally requires you to handle the casting yourself.

Some R data types can be automatically converted to Java types when given to a method or constructor.

R vector (length>1)Java
R vector (length==1)Java

An R object can be converted to other basic Java data types with .jfloat, .jlong, .jbyte, .jchar and .jshort. If an R vector of length 1 needs to be passed as an array, simply wrap it in a .jarray call.

> .jfloat(1)
An object of class "jfloat"
[1] 1
> .jlong(1)
An object of class "jlong"
[1] 1
> .jbyte(1)
An object of class "jbyte"
[1] 1
> .jchar(1)
An object of class "jchar"
[1] 1
> .jshort(1)
An object of class "jshort"
[1] 1
> .jarray(1)
[1] "Java-Array-Object[D:[D@287a3"

Where to go from here...

You can do quite a bit with the above. A good place to start if/when you run into trouble is the rJava Documentation. If that fails and it is an rJava related problem, try the mailing list.

Continue to Building dialogs in R