Manipulation of Java references.
The
ocamljava
compiler allows to manipulate Java references through
two types, namely
cn java_instance
and
cn java_extends
. The
former is used to designate instances of exactly one class, while
the latter is used to designate instances of either one class or
any of its subclasses. In both cases, the type parameter is used to
specify the class. It uses the fully-qualified name of the class,
just replacing dots with single quotes. The type of Java strings is
thus written
java'lang'String java_instance
.
This module contains the functions needed to create new instances,
call methods, and access fields. Such functions use
descriptors
to determine the constructor/method/field to use. These descriptors
are written as string litterals; for example, parsing a string into
an integer can be done by writing:
let integer = call "java.lang.Integer.parseInt(java.lang.String):int" s
However, it is possible to use simple names rather than qualified
names for classes if their packages have been opened. Initially, the
java.lang package is the only one opened. A package can be opened
though a modified
open Package'packname
directive; for example
opening the
javax.awt package can be done by writing:
open Package'java'awt
It is also possible to take advantage of opened packages in types, by
replacing the package name with an underscore. The type of Java
strings can thus be written
_'String java_instance
.
Moreover, types of fields and return types of methods can be elided
as long as there is no ambiguity. Types of method/constructor
parameters can also be replaced with single underscores, leading to
the lighter code to parse an integer:
let integer = call "Integer.parseInt(_)" s
Furthermore, it is possible to use dashes to denote any number of
parameters, leading to the lightest code to rotate an integer value:
let y = call "Integer.rotateLeft(-)" x bits
The compiler will issue an error if there is an ambiguity.
When calling a method with a variable number of arguments, two
variants are accepted for the descriptor, impacting how the arguments
should be passed:
Finally, two exceptions are defined to wrap Java exceptions on the
OCaml side:
exception Java_exception of java'lang'Exception java_instance
exception Java_error of java'lang'Error java_instance
Warning: to be able to use the functions from this module, java
extensions should be enabled by passing the
-java-extensions
option
to the
ocamljava
compiler.
val proxy_loader : 'a java_proxy -> java'lang'ClassLoader java_extends -> 'a
proxy_loader "interfacenames" cl impl
returns an instance that
implements
interfacenames
(a comma-separated list of interface
names) using the methods provided by
impl
. The class is defined in
the class loader
cl
.
For example, an instance of
java.lang.Runnable can be built using
the following code:
proxy "java.lang.Runnable" (object
method run = ...
end)
When only one interface is provided, the instance returned by
proxy
has this type, otherwise it has type
java.lang.Object.
It is also possible to override methods from the
java.lang.Object
class (independently of their presence/absence in any of the
interfaces). To this end, it is possible to use the
.methodName
notation in the interface list. As of Java 1.7, only three methods
can be overridden:
toString,
equals, and
hashCode. For
example, an instance of
java.lang.Runnable overriding
toString
can be built using the following code:
proxy "java.lang.Runnable, .toString" (object
method run = ...
method toString = ...
end)