Creating Java Objects
The Basics
Before using Java in our Matlab application, we first need to ensure that Java is supported
on our specific Matlab installation (which it should, normally) this check is done using
Matlab’s built-in functions usejava or javachk (which is just a wrapper for usejava) † there
are four documented levels of Java that can be checked (“jvm”, “awt”, “swing”, and “desktop”3);
an additional undocumented level (“mwt”) checks for MathWorks Swing extensions used by
custom Matlab controls (see Chapter 5):
if ~usejava('jvm')
error('this feature requires Java');
end
error(javachk('jvm','this feature requires Java')); % equivalent
Java code is based on classes that group Java functionality (functions or methods) and properties
Methods and properties, as well as the classes themselves, have access modifiers, which
determine whether they can be accessed outside the class’s methods Matlab can only access
Java elements that are declared to have a public access modifier Classes are grouped into packages
and can be extended by new classes that add new functionality or modify (override) existing
ones
to use Java classes, we create (instantiate) objects of their type, and then use their classes’
public-access methods Instantiation can only be done if the class has a constructor method,
which is basically just a method named exactly as its class’s name, and declared without any
return value (unlike all other class methods) alternately, we can use the classes’ static methods
without needing any object Matlab’s class object system (MCOS)4 uses many of these concepts,
although the actual implementation of classes and modifiers looks different than in Java
the simplest way to integrate a standard Java class in Matlab is to directly invoke its
constructor method, getting an object reference in return:
>> java.awt.Dimension % default constructor (no args)
ans =
java.awt.Dimension[width = 0,height = 0]
>> dim = java.awt.Dimension(12,25) % non-default constructor
dim =
java.awt.Dimension[width = 12,height = 25]
>> java.lang.Thread % a different example
ans =
Thread[Thread-161,5,main] <= note the different representation format
Matlab can only access publicly accessible methods and classes Due to this, Matlab
cannot instantiate objects from Java classes that do not have a publicly accessible constructor
Forgetting to declare both the class and its constructor(s) as public is a common cause of error
when trying to use Java classes in Matlab
Static public methods can be invoked using the class name, even when the class does not
have a public-access constructor and no objects can be instantiated from it:
>> % MJUtilities has no public constructor so it can't be instantiated
>> object = com.mathworks.mwswing.MJUtilities;
??? No constructor 'com.mathworks.mwswing.MJUtilities' with matching signature
found.
>> % This uses the MJUtilities class's static public beep method
>> com.mathworks.mwswing.MJUtilities.beep; % no error (beep sound)
Some Java classes have both public constructor(s) and static methods In such cases, we can
instantiate class objects and can call the static methods either via the class object or directly via
the class name:
% Three different ways to instantiate a Color object:
>> color = java.awt.Color(1,0.7,0.5) % use a regular constructor
color =
java.awt.Color[r = 255,g = 179,b = 128]
>> color = java.awt.Color.cyan % use a static property
color =
java.awt.Color[r = 0,g = 255,b = 255]
>> color = java.awt.Color.decode('0xff00ff') % use a static method
c =
java.awt.Color[r = 255,g = 0,b = 255]
>> % Instantiate a Java Frame object and use it to list active frames
>> jFrame = java.awt.Frame
jFrame =
java.awt.Frame[frame0,0,0,0x0,invalid,hidden,layout = java.awt.
BorderLayout,title = ,resizable,normal]
>> jFrame.getFrames % or: getFrames(jFrame)
ans =
java.awt.Frame[]:
[com.mathworks.mde.desk.MLMainFrame ]
[com.mathworks.mde.desk.MLMultipleClientFrame]
[com.mathworks.mwswing.MJFrame ]
[javax.swing.SwingUtilities$SharedOwnerFrame ]
[com.mathworks.mwswing.MJFrame ]
[java.awt.Frame ]
>> % getFrames() is a public static method, therefore we don't need
>> % to instantiate an object in order to use it in MaTLaB:
>> java.awt.Frame.getFrames
ans =
java.awt.Frame[]:
[com.mathworks.mde.desk.MLMainFrame ]
[com.mathworks.mde.desk.MLMultipleClientFrame]
...
Java classes can also be created using Matlab’s javaObject function, which is useful
when the fully qualified class name (FQCN) is long or when the class name is stored in a program
variable Such cases are usually rare
a more common need is to create instances of Java nested-classes Nested classes are classes
that are defined within the context of a parent class In Java source code, they are referred to
using dot-notation (e g , Package.Name.ParentClassName.NestedName), although
their class file name uses “$” (ParentClassName$NestedName.class) this confuses Matlab
into thinking that the nested class is called ParentClassName$NestedName (with a $)
Unfortunately, since “$” is not a valid Matlab character, we cannot directly create any
instance of such a class the solution is to use javaObject:5
>> jObject = javax.swing.ScrollPaneLayout.UIResource6
??? No appropriate method, property, or field UIResource for class javax.swing.
ScrollPaneLayout.
>> jObject = javax.swing.ScrollPaneLayout$UIResource
??? jObject = javax.swing.ScrollPaneLayout$UIResource
|
Error: The input character is not valid in MaTLaB statements or expressions.
>> jObject = javaObject('javax.swing.ScrollPaneLayout$UIResource')
jObject =
javax.swing.ScrollPaneLayout$UIResource@695c5b
Yet another form of Java object creation is using the unsupported semidocumented awtcreate
function the main difference between javaObject and awtcreate is that javaObject is
executed immediately, in the main Matlab computational thread, whereas awtcreate is
placed on the Java aWt† Event Dispatch Thread (EDt; described in Section 3 2) and executed
only after all the other pending aWt events have ended awtcreate is typically needed when
constructing Java GUI components that rely on other GUI commands to finish first In all other
cases, use of awtcreate is discouraged — its cumbersome JNI notation7 argument format
ensures that programmers would normally and rightly not use this function
Matlab release R2008a (7 6) added an important addition solving much of the awtcreate
and awtinvoke (see below) frustration: javaObjectEDT (and the corresponding javaMethodEDT)
behaves just like javaObject (and javaMethod) except that it runs on the EDt, without
any of the cumbersomeness of awtcreate (and awtinvoke) Moreover, javaObjectEDT accepts
any reference of an existing Java object and ensures that all method invocations on this reference
object from that point onward will automatically be dispatched on the EDt without any
code change Unfortunately, I have found that relying on R2008a (7 6)’s version of javaObjectEDT
sometimes causes Matlab to hang as far as I could test, this was corrected in Matlab
release R2008b (7 7), and since then it is most advisable to use javaObjectEDT for all GUIrelated
Java components (subclasses of java.awt.* or javax.swing.*) ‡