25.1 Importing Java Packages in Jython
Unlike Java, Jython does not implicitly
and automatically import java.lang. Your Jython
code can explicitly import
java.lang, or even just import
java, and then use classes such as
java.lang.System and
java.lang.String as if they were Python classes.
Specifically, your Jython code can use imported Java classes as if
they were Python classes with a _ _slots_ _ class
attribute (i.e., you cannot create arbitrary new instance
attributes). You can subclass a Java class with your own Python
class, and instances of your class let you create new attributes just
by binding them, as usual.
You may choose to import a top-level Java package (such as
java) rather than specific subpackages (such as
java.lang). Your Python code acquires the ability
to access all subpackages when you import the top-level package. For
example, after import java,
your code can use classes java.lang.String,
java.util.Vector, and so on.
The Jython runtime wraps every Java class you import in a transparent
proxy, which manages communication between Python and Java code
behind the scenes. This gives an extra reason to avoid the dubious
idiom from somewhere
import *, in addition to the
reasons mentioned in Chapter 7. When you perform
such a bulk import, the Jython runtime must build proxy wrappers for
all the Java classes in package somewhere,
spending substantial amounts of memory and time wrapping classes your
code will probably not use. Avoid from
... import *
except for occasional convenience in interactive exploratory
sessions, and stick with the import statement.
Alternatively, it's okay to use specific, explicit
from statements for classes you know your Python
code wants to use (e.g., from
java.lang import
System).
25.1.1 The Jython Registry
Jython relies on a
registry of Java properties as a cross-platform
equivalent of the kind of settings that would normally use the
Windows registry, or environment variables on Unix-like systems.
Jython's registry file is a standard Java properties
file named registry, located in a directory
known as the Jython root directory. The Jython root directory is
normally the directory where jython.jar is
located, but you can override this by setting Java properties
python.home or install.root.
For special needs, you may tweak the Jython registry settings via an
auxiliary Java properties file named .jython in
your home directory, and/or via command-line options to the
jython interpreter command. The registry option
python.path is equivalent to classic
Python's PYTHONPATH environment
variable. This is the option you may most often be interested in, as
it can help you install extra Python packages outside of the Jython
installation directories (e.g., sharing Python packages installed for
CPython use).
25.1.2 Accessibility
Normally,
your Jython code can access only public features
(methods, fields, inner classes) of Java classes. You may choose to
make private and protected
features available by setting an option in the Jython registry before
you run Jython:
python.security.respectJavaAccessibility=false
Such bending of normal Java rules should never be necessary for
normal operation. However, the ability to access private and
protected features may be useful to Jython scripts meant to
thoroughly test a Java package, which is why Jython gives you this
option.
25.1.3 Type Conversions
The Jython runtime converts data
between Python and Java transparently. However, when a Java method
expects a boolean argument, you have to pass an
int or an instance of
java.lang.Boolean in order to call that method
from Python. In Python, any object can be taken as true or false, but
Jython does not perform the conversion to boolean
implicitly on method calls, to avoid confusion and the risk of
errors.
25.1.3.1 Calling overloaded Java methods
A Java class can supply overloaded methods
(i.e., several methods with the same name, distinguished by the
number and types of their arguments). Jython resolves calls to
overloaded methods at runtime, based on the number and types of
arguments that Python code is passing in each given call. If
Jython's automatic overload resolution is not giving
the results you expect, you can help it along by explicitly passing
instances of Java's java.lang
wrapper classes, such as java.lang.Integer where
the Java method expects an int argument,
java.lang.Float where the Java method expects a
float argument, and so on. For example, if a Java
class C supplies a method named
M in two overloaded versions,
M(long x) and
M(int x), consider the
following Python code:
import C, java.lang
c = C( )
c.M(23) # calls M(long)
c.M(java.lang.Integer(23)) # calls M(int)
c.M(23) calls the long
overloaded method, due to the rules of Jython overload resolution.
c.M(java.lang.Integer(23)), however, explicitly
calls the int overloaded method.
25.1.3.2 The jarray module
When you pass
Python sequences to Java methods that expect array arguments, Jython
performs automatic conversion, copying each item of the Python
sequence into an element of the Java array. When you call a Java
method that accepts and modifies an array argument, the Python
sequence that you pass cannot reflect any changes the Java method
performs on its array argument. To let you effectively call methods
that change their array arguments, Jython offers module
jarray, which supplies two factory functions that
let you build Java arrays directly.
seq is any Python sequence.
typecode is either a Java class or a
single character (specifying a primitive Java type according to Table 25-1). array creates a Java
array a with the same length as
seq and elements of the class or type
given by typecode.
array initializes
a's elements from
seq's corresponding
items.
Table 25-1. Typecodes for the jarray module
'b'
|
byte
|
'c'
|
char
|
'd'
|
double
|
'f'
|
float
|
'h'
|
short
|
'i'
|
int
|
'l'
|
long
|
'z'
|
boolean
|
Creates a Java array z with length
length and elements of the class or type
given by typecode, which has the same
meaning as in function array.
zeros initializes each element of
z to 0,
null, or false, as appropriate
for the type or class. Of course, when you access such elements from
Jython code, you see them as the equivalent Python
0 values (or None as the Jython
equivalent of Java null), but when Java code
accesses the elements, it sees them with the appropriate Java types
and values.
You can use instances created by functions array
and zeros as Python sequences of fixed length.
When you pass such an instance to a Java method that accepts an array
argument and modifies the argument, the changes are visible in the
instance, so your Python code can effectively call such methods.
25.1.3.3 The java.util collection classes
Jython performs no automatic conversion
either way between Python containers and the collection classes of
package java.util, such as
java.util.Vector,
java.util.Dictionary, and so on. However, Jython
adds to the wrappers it builds for the Java collection classes a
minimal amount of support to let you treat instances of collection
classes as Python sequences, iterables, or mappings, as appropriate.
25.1.4 Subclassing a Java Class
A Python class may inherit from a
Java class (equivalent to Java construct extends)
and/or from Java interfaces (equivalent to Java construct
implements), as well as from other Python classes.
A Jython class cannot inherit, directly or indirectly, from more than
one Java class. There is no limit on inheriting from interfaces. Your
Jython code can access protected methods of the
Java superclass, but not protected fields. You can
override non-final superclass methods. In
particular, you should always override the methods of interfaces you
inherit from. If a method is overloaded in the superclass, your
overriding method must support all of the signatures of the
overloads. To accomplish this, you can define your method to accept a
variable number of arguments (by having its last formal argument use
special form *args) and
check at runtime as needed for the number and types of arguments you
receive on each call.
25.1.5 JavaBeans
Jython offers
special support for the typical JavaBeans idiom of naming accessor
methods getSomeThing,
isSomeThing,
setSomeThing. When such
methods exist in a Java class, Python code can access and set a
property named someThing on instances of
that Java class, using the Python syntax of attribute access and
binding. The Jython runtime transparently translates such accesses
into calls to appropriate accessor methods.
|