[ Team LiB ] Previous Section Next Section

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.

array

array(seq,typecode)

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

Typecode

Java type

'b'
byte
'c'
char
'd'
double
'f'
float
'h'
short
'i'
int
'l'
long
'z'
boolean

zeros

zeros(length,typecode)

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.

    [ Team LiB ] Previous Section Next Section