Python DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Jython Tips for Python Programmers
Pages: 1, 2

4. Accessing Methods and Fields

Normally from Jython you can call any Java method or field designated as public in the Java class. You can get at private methods by changing Jython's start-up options.



Jython also allows you to avoid the ubiquitous Java get/set methods, allowing your program to have a more Pythonic style. When Jython sees a line of code such as:

x = javaObj.attribute

a Java call of the method javaObj.getAttribute(), if such a method exists, is automatically generated. Similarly, an assignment to javaObj.attribute is converted to a call to javaObj.setAttribute.

5. Creating Java Arrays

Frequently, you will need to call a Java method that requires a Java array as an argument. Under normal circumstances, Jython will automatically convert a Python list or tuple to an array of the appropriate type when needed. This assumes that each item in the list or tuple can be converted to the appropriate type -- if not, Jython will raise a runtime error. So the Jython list [1, 2, 3] can be converted to a Java int[], long[], java.lang.Integer[], or java.lang.Object[] as needed (but not, for example, to a java.lang.String[]).

However, that conversion creates a copy of the list, and in some cases that's not what you want. For example, if the method you are calling changes the list in-place, the change will not propagate back to the Jython code, since the array is only a copy of the Jython list. Jython provides the jarray module to simplify the direct creation of Java arrays when needed.

You can create blank arrays with the zeros method.

>>> import jarray
>>> jarray.zeros(5, 'i')
array([0, 0, 0, 0, 0], int)

The first argument is the length of the array, and the second is either a character representing a basic type, or a Java class name.

>>> jarray.zeros(4, java.lang.String)
array([None, None, None, None], java.lang.String)

You can create arrays directly from Python sequences, by using the array method.

>>> jarray.array([8, 9, 2, 1], 'i')
array([8, 9, 2, 1], int)

Now, the first argument is a Python sequence, and the second is still the class or type signature.

6. Overloaded Methods

In the case where the Java method is overloaded and has more than one definition, Jython will attempt to match the call to the correct method based on the number and runtime type of the arguments.

Although the details can get complex, the basic idea is simple: Jython first attempts to choose a method with the same number of arguments as the call, and if there is more than one, it chooses the method whose required type is most similar to the calling object. In general, Jython prefers methods with basic Java types over methods with Java object types.

7. Subclassing Java Objects

A Jython object can be declared as a subclass of a Java object by using the standard Python syntax:

class JythonString(java.lang.String):
    pass

Java interfaces can also be implemented in this way. Jython does not do a compile-time check to determine if all methods in an interface are actually defined -- calling an undefined method will raise a runtime exception.

Although Jython does have multiple inheritance, there is one limitation concerning Java objects. A Jython class can have at most one Java ancestor. This is true whether the ancestor is a direct parent, or an indirect parent via another Jython class.

Java subclasses behave differently when constructed. If a Jython class has a Java parent, and that parent has a no-argument constructor, that constructor is automatically called at the end of the Jython class' __init__ method, or before a Java attribute is used within that __init__ method. This is different from the normal Python behavior, where a parent class constructor is never called automatically. This is done to ensure that the Java objects are properly initialized before use.

8. Adding Attributes

Unlike ordinary Python objects, you cannot create new attributes in a Java object instance simply by assigning to it -- the instance must have been declared in Java. Attempting to assign to an instance of a Java class that does not exist will raise an error.

>>> x = java.util.ArrayList()
>>> x.language = 'english'
Traceback (innermost last):

  File "console", line 1, in ?

TypeError: can't set arbitrary attribute in java instance: language

To work around this limitation, you can create a subclass of the Java class -- it can be an empty subclass. You can then add attributes to instances of the subclass:

>>> class NewArrayList(java.util.ArrayList):
...     pass
... 
>>> x = NewArrayList()
>>> x.language = 'english'
>>> x.language
'english'

9. Serialization

Java objects cannot be serialized using the standard Python pickle and cPickle modules. Both Java and Jython objects can be serialized using normal Java serialization. However, when deserializing a Jython object you cannot use the normal java.io.ObjectInputStream class, you must use the Jython-specific org.python.util.PythonObjectInputStream, as shown here:

import java.io as io
import org.python.util as util

class TestClass(io.Serializable):
    def __init_ _(self, value=0):
        self.value = value
        self.message = "Serialized"

    def toString(self):
        return "Message: %(message)s value: 
          is %(value)s" % self.__dict_ _

instance = TestClass(3)

outFile = io.FileOutputStream("test.ser")
outStream = io.ObjectOutputStream(outFile)
outStream.writeObject(instance)
outFile.close( )

inFile = io.FileInputStream("test.ser")
inStream = util.PythonObjectInputStream(inFile)

readInstance = inStream.readObject( )
print readInstance.toString( )
Message: Serialized value: is 3

If you do not use the PythonObjectInputStream, you will get a runtime error because the ordinary Java ObjectInputStream has difficulty finding and recreating the dynamically loaded proxy classes used for Jython's Java inheritance.

10. Special Bonus Differences

Finally, here are a few of the most important differences between Jython and Cpython, not directly related to object usage:

  • All Jython strings are Unicode based, therefore all distinctions between regular and Unicode strings that exist in CPython are ignored in Jython.
  • Since some Python keywords are common Java methods (like print), Jython is more flexible than CPython about allowing keywords as identifiers in places where the meaning is unambiguous (such as after a '.').
  • Jython uses Java garbage collection, not Cpython-style reference counting for memory management.
  • Jython does not recognize the -O optimization flag.
  • Jython file objects are missing some of the functionality of their CPython equivalents, due to missing features in the JVM. Similarly, some CPython modules, most notably, os, sys, and socket, are missing functionality.
  • CPython libraries written in C may not have been ported to Jython, and may not be usable (for example, Tkinter).

For more information on Jython, see the main Jython site at http://www.jython.org, and get a copy of our recent book, Jython Essentials.

Noel Rappin has a Ph.D. in computer science from the Georgia Institute of Technology, where his research included methods for teaching Object-Oriented Programming and Design. He has extensive production experience in both Java and Python.


Return to the Python DevCenter.





Sponsored by: