This part of the documentation covers all the interfaces of Pyjnius.
Base for reflecting a Java class. The idea is to subclass this JavaClass, add few JavaMethod, JavaStaticMethod, JavaField, JavaStaticField, and you’re done.
You need to define at minimum the __javaclass__ attribute, and set the __metaclass__ to MetaJavaClass.
So the minimum class definition would look like:
from jnius import JavaClass, MetaJavaClass
class Stack(JavaClass):
__javaclass__ = 'java/util/Stack'
__metaclass__ = MetaJavaClass
Must be set to MetaJavaClass, otherwise, all the methods/fields declared will be not linked to the JavaClass.
Represent the Java class name, in the format ‘org/lang/Class’. (eg: ‘java/util/Stack’), not ‘org.lang.Class’.
If not set, we assume the default constructor to take no parameters. Otherwise, it can be a list of all possible signatures of the constructor. For example, a reflection of the String java class would look like:
class String(JavaClass):
__javaclass__ == 'java/lang/String'
__metaclass__ = MetaJavaClass
__javaconstructor__ == (
'()V',
'(Ljava/lang/String;)V',
'([C)V',
'([CII)V',
# ...
)
Reflection of a Java method.
Create a reflection of a Java method. The signature is in the JNI format. For example:
class Stack(JavaClass):
__javaclass__ = 'java/util/Stack'
__metaclass__ = MetaJavaClass
peek = JavaMethod('()Ljava/lang/Object;')
empty = JavaMethod('()Z')
The name associated to the method is automatically set from the declaration within the JavaClass itself.
The signature can be found with the javap -s. For example, if you want to fetch the signatures available for java.util.Stack:
$ javap -s java.util.Stack
Compiled from "Stack.java"
public class java.util.Stack extends java.util.Vector{
public java.util.Stack();
Signature: ()V
public java.lang.Object push(java.lang.Object);
Signature: (Ljava/lang/Object;)Ljava/lang/Object;
public synchronized java.lang.Object pop();
Signature: ()Ljava/lang/Object;
public synchronized java.lang.Object peek();
Signature: ()Ljava/lang/Object;
public boolean empty();
Signature: ()Z
public synchronized int search(java.lang.Object);
Signature: (Ljava/lang/Object;)I
}
Reflection of a static Java method.
Reflection of a Java field.
Create a reflection of a Java field. The signature is in the JNI format. For example:
class System(JavaClass):
__javaclass__ = 'java/lang/System'
__metaclass__ = MetaJavaClass
out = JavaField('()Ljava/io/InputStream;', static=True)
The name associated to the method is automatically set from the declaration within the JavaClass itself.
Reflection of a static Java field
Reflection of a Java method that can be called from multiple signatures. For example, the method getBytes in the String class can be called from:
public byte[] getBytes(java.lang.String)
public byte[] getBytes(java.nio.charset.Charset)
public byte[] getBytes()
Let’s see how you could declare that method:
class String(JavaClass):
__javaclass__ = 'java/lang/String'
__metaclass__ = MetaJavaClass
getBytes = JavaMultipleMethod([
'(Ljava/lang/String;)[B',
'(Ljava/nio/charset/Charset;)[B',
'()[B'])
Then, when you will try to access to this method, we’ll take the best method available according to the type of the arguments you’re using. Internally, we are calculating a “match” score for each available signature, and take the best one. Without going into the details, the score calculation look like:
Base for creating a Java class from a Python class. This allow to implement java interface completely in Python.
In reality, you’ll create a Python class that mimic the list of declared __javainterfaces__. When you’ll give an instance of this class to Java, Java will just accept it and call the interfaces methods as declared. Under the hood, we are catching the call, and redirecting to use your declared Python method.
Your class will act as a Proxy to the Java interfaces.
You need to define at minimum the __javainterfaces__ attribute, and declare java methods with the java_method() decorator.
Note
Static methods and static fields are not supported
For example, you could implement the java/util/ListIterator interface in Python like that:
from jnius import PythonJavaClass, java_method
class PythonListIterator(PythonJavaClass):
__javainterfaces__ = ['java/util/ListIterator']
def __init__(self, collection, index=0):
super(TestImplemIterator, self).__init__()
self.collection = collection
self.index = index
@java_method('()Z')
def hasNext(self):
return self.index < len(self.collection.data) - 1
@java_method('()Ljava/lang/Object;')
def next(self):
obj = self.collection.data[self.index]
self.index += 1
return obj
# etc...
List of the Java interfaces you want to proxify, in the format ‘org/lang/Class’. (eg: ‘java/util/Iterator’), not ‘org.lang.Class’.
Decoration function to use with PythonJavaClass. The java_signature must match the wanted signature of the interface. The name of the method will be the name of the Python method by default. You can still force it, in case of multiple signature with the same Java method name.
For example:
class PythonListIterator(PythonJavaClass):
__javainterfaces__ = ['java/util/ListIterator']
@java_method('()Ljava/lang/Object;')
def next(self):
obj = self.collection.data[self.index]
self.index += 1
return obj
Another example with the same Java method name, but 2 differents signatures:
class TestImplem(PythonJavaClass):
__javainterfaces__ = ['java/util/List']
@java_method('()Ljava/util/ListIterator;')
def listIterator(self):
return PythonListIterator(self)
@java_method('(I)Ljava/util/ListIterator;',
name='ListIterator')
def listIteratorWithIndex(self, index):
return PythonListIterator(self, index)
Java signatures have a special format that could be difficult to understand at first. Let’s see in details. A signature is in the format:
(<argument1><argument2><...>)<return type>
All the types for any part of the signature can be one of:
All the types can have the [] suffix to design an array. The return type can be V or empty.
A signature like:
(ILjava/util/List;)V
-> argument 1 is an integer
-> argument 2 is a java.util.List object
-> the method doesn't return anything.
(java.util.Collection, java.lang.Object[]);
-> argument 1 is a Collection
-> argument 2 is an array of Object
-> nothing is returned
When you implement Java in Python, the signature of the Java method must match. Java provide a tool named javap to get the signature of any java class. For example:
$ javap -s java.util.Iterator
Compiled from "Iterator.java"
public interface java.util.Iterator{
public abstract boolean hasNext();
Signature: ()Z
public abstract java.lang.Object next();
Signature: ()Ljava/lang/Object;
public abstract void remove();
Signature: ()V
}