You can call a Java method as if it were a Scheme procedure using various mechanisms.
The most convenient way to do it is to
use define-namespace to define an alias for a Java class:
(define-namespace Int32 "class:java.lang.Integer")
In this example the name Int32 is a namespace alias
for the namespace whose full name is "class:java.lang.Integer".
The full name should be the 6 characters "class:" followed
by the fully-qualified name of a Java class.
Equivalently, you can use a name for a class, such as:
(define-namespace Int32 <java.lang.Integer>)
The latter syntax also works for classes defined in the module, or aliases, since the name is first searched in the lexical scope.
You can name a method using a qualified name containing a colon.
The part of the name before the colon is a namespace alias (in
this case Int32), and the part of the name after the colon is the
method name.  For example:
(Int32:toHexString 255) => ff
This invokes the static method toHexString in the
Java class java.lang.Integer, passing it the argument 255,
and returning the Java String "ff".  (Note this is not the
same as a Scheme string!)
The general syntax is
(prefix:method-namearg...)
This invokes the method named method-name in the class corresponding
to prefix, and the args are the method arguments.
You can use the method name new to construct new objects:
(Int32:new '|255|)
This is equivalent to the Java expression new Integer("255").
You can also write:
(Int32:new "255")
Kawa is smart enough to convert the Kawa string to a Java String.
To invoke a non-static method you can use a special prefix *:
(*:toString (list 9 8 7))
The general syntax is
(*:method-nameinstancearg...)
This invokes the method named method-name
with instance as the target object, and the args are
the method arguments.
Alternatively, you can invoke a non-static method using an explicit
prefix:
(prefix:method-nameinstancearg...)
Assuming that prefix is bound to class then the
above is equivalent to:
(*:method-name(asclassinstance)arg...)
For example:
(Int32:doubleValue (Int32:new "00255"))
This returns the double value 255.0.
As a shorthand, you can use the name of a Java class instead of a namespace alias:
(java.lang.Integer:toHexString 255) (java.lang.Object:toString some-value)
If Kawa sees a qualified name with a prefix that is not defined and
that matches the name of a known class, then Kawa will automatically
treat the prefix
as a nickname for namespace uri like class:java.lang.Integer.
Both conditions should be true at both compile-time and run-time.
However, using an explicit define-namespace is recommended.
As a final shorthand you can use an identifier in handle brackets,
such as an existing type alias like <list>.
The following are all equivalent:
(<list>:list3 'a 'b 'c)
This is equivalent to:
(define-namespaceprefix<list> (prefix:list3 'a 'b 'c)
for some otherwise-unused prefix.
If you prefer, you can instead use the following functions. (There is also an older deprecated lower-level interface (see Low-level Method invocation.)
Function: invoke-static class name args ...
The
classcan be a<java.lang.Class>, a<gnu.bytecode.ClassType>, or a<symbol>or<string>that names a Java class. Thenamecan be<symbol>or<string>that names one or more methods in the Java class.Any accessible methods (static or instance) in the specified
class(or its super-classes) that match "name" or "name$V" collectively form a generic procedure. When the procedure is applied to the argument list, the most specific applicable method is chosen depending on the argument list; that method is then called with the given arguments. Iff the method is an instance method, the first actual argument is used as thethisargument. If there are no applicable methods (or no methods at all!), or there is no "best" method,WrongTypeis thrown.An example (derived from the Skij FAQ):
(invoke-static <java.lang.Thread> 'sleep 100)The behavior of interpreted code and compiled code is not identical, though you should get the same result either way unless you have designed the classes rather strangely. The details will be nailed down later, but the basic idea is that the compiler will "inline" the
invoke-staticcall if it can pick a single "best" matching method.
Function: invoke object name args ...
The
namecan be<symbol>or<string>that names one or more methods in the Java class.Any accessible methods (static or instance) in the specified
class(or its super-classes) that match "name" or "name$V" collectively form a generic procedure. When the procedure is applied to the argument list, the most specific applicable method is chosen depending on the argument list; that method is then called with the given arguments. Iff the method is an instance method, theobjectis used as thethisargument; otherwiseobjectis prepended to theargslist. If there are no applicable methods (or no methods at all!), or there is no "best" method,WrongTypeis thrown.The behavior of interpreted code and compiled code is not indentical, though you should get the same result either way unless you have designed the classes rather strangely. The details will be nailed down later, but the basic idea is that the compiler will "inline" the
invoke-staticcall if it can pick a single "best" matching method.If the compiler cannot determine the method to call (assuming the method name is constant), the compiler has to generate code at run-time to find the correct method. This is much slower, so the compiler will print a warning. To avoid a waning, you can use a type declaration, or insert a cast:
(invoke (as <java.util.Date> my-date) 'setDate cur-date)or
(let ((my-date :: <java.util.Date> (calculate-date)) (cur-date :: <int> (get-cur-date))) (invoke my-date 'setDate cur-date))
Function: invoke-special class receiver-object name arg ...
The
classcan be a<java.lang.Class>, a<gnu.bytecode.ClassType>, or a<symbol>or<string>that names a Java class. Thenamecan be<symbol>or<string>that names one or more methods in the Java class.This procedure is very similar to
invokeandinvoke-staticand invokes the specified method, ignoring any methods in subclasses that might overide it. One interesting use is to invoke a method in your super-class like the Java languagesuperkeyword.Any methods in the specified
classthat match "name" or "name$V" collectively form a generic procedure. That generic procedure is then applied as ininvokeusing thereceiver-objectand the arguments (if any).The compiler must be able to inline this procedure (because you cannot force a specific method to be called using reflection). Therefore the
classandnamemust resolve at compile-time to a specific method.(define-simple-class <MyClass> (<java.util.Date>) ((get-year) :: <int> (+ (invoke-special <java.util.Date> (this) 'get-year)) 1900) ((set-year (year :: <int>)) :: <void> (invoke-special <java.util.Date> (this) 'set-year (- year 1900))))
Function: class-methods class name
Return a generic function containing those methods of
classthat match the namename, in the sense ofinvoke-static. Same as:(lambda args (apply invoke-static (cons class (cons name args))))
Some examples using these functions are ‘vectors.scm’
and ‘characters.scm’ the directory ‘kawa/lib’ in
the Kawa sources.
All of the above select a method to invoke base on specified
method name and argments.  If specified name is not a Java name,
it is "mangled" (see Mapping Scheme names to Java names) into a valid Java name.
All accessible methods whose names match are considered.
Methods that match after appending $V or $X or $V$X
are also considered.  A $V suffix matches a variable
number of arguments:  any excess arguments are collect into an
gnu.lists.LList or a Java array (depending on the final parameter type).
A $X specifies that the method expects an extra implicit
CallContext parameter.  In that case the method's result is written
to the CallContext, so the method result type must be void.
(Kawa compiles a procedure with a #!rest or keyword args
whose name is fnfn$V