0
# Java-Python Integration
1
2
Jython provides seamless integration between Java and Python, allowing automatic type conversion, method invocation, and exception handling across both platforms.
3
4
## Type Conversion
5
6
### Java to Python Conversion
7
8
Automatic conversion from Java objects to Python objects.
9
10
```java { .api }
11
public final class Py {
12
// Generic conversion
13
public static PyObject java2py(Object o);
14
15
// Specific conversions
16
public static PyString java2py(String s);
17
public static PyInteger java2py(int i);
18
public static PyInteger java2py(long l);
19
public static PyFloat java2py(float f);
20
public static PyFloat java2py(double d);
21
public static PyBoolean java2py(boolean b);
22
public static PyObject java2py(Object o);
23
}
24
```
25
26
### Python to Java Conversion
27
28
Convert Python objects back to Java types.
29
30
```java { .api }
31
public abstract class PyObject {
32
// Generic conversion
33
public Object __tojava__(Class<?> c);
34
35
// Common conversions available on specific types
36
public String toString();
37
public boolean equals(Object o);
38
public int hashCode();
39
}
40
41
// Specific conversion methods on respective classes
42
public class PyString {
43
public String getString();
44
public String asString();
45
}
46
47
public class PyInteger {
48
public int getValue();
49
public int asInt();
50
public long asLong();
51
public double asDouble();
52
}
53
54
public class PyFloat {
55
public double getValue();
56
public double asDouble();
57
public int asInt();
58
}
59
60
public class PyBoolean {
61
public boolean getBooleanValue();
62
public boolean __bool__();
63
}
64
```
65
66
## Usage Examples
67
68
### Basic Type Conversion
69
70
```java
71
// Java to Python
72
String javaStr = "Hello, World!";
73
PyString pyStr = Py.java2py(javaStr);
74
75
int javaInt = 42;
76
PyInteger pyInt = Py.java2py(javaInt);
77
78
double javaDouble = 3.14159;
79
PyFloat pyFloat = Py.java2py(javaDouble);
80
81
boolean javaBool = true;
82
PyBoolean pyBool = Py.java2py(javaBool);
83
84
// Python to Java
85
String backToJava = pyStr.getString();
86
int backToInt = pyInt.asInt();
87
double backToDouble = pyFloat.asDouble();
88
boolean backToBool = pyBool.getBooleanValue();
89
```
90
91
### Collection Conversion
92
93
```java
94
// Java List to Python List
95
List<String> javaList = Arrays.asList("apple", "banana", "cherry");
96
PyList pyList = new PyList();
97
for (String item : javaList) {
98
pyList.append(Py.java2py(item));
99
}
100
101
// Python List to Java List
102
List<String> backToJavaList = new ArrayList<>();
103
for (int i = 0; i < pyList.__len__(); i++) {
104
PyObject item = pyList.__getitem__(i);
105
backToJavaList.add(item.toString());
106
}
107
```
108
109
### Map Conversion
110
111
```java
112
// Java Map to Python Dictionary
113
Map<String, Object> javaMap = new HashMap<>();
114
javaMap.put("name", "Alice");
115
javaMap.put("age", 30);
116
javaMap.put("active", true);
117
118
PyDictionary pyDict = new PyDictionary();
119
for (Map.Entry<String, Object> entry : javaMap.entrySet()) {
120
PyString key = Py.java2py(entry.getKey());
121
PyObject value = Py.java2py(entry.getValue());
122
pyDict.put(key, value);
123
}
124
125
// Python Dictionary to Java Map
126
Map<String, Object> backToJavaMap = new HashMap<>();
127
PyList keys = pyDict.keys();
128
for (int i = 0; i < keys.__len__(); i++) {
129
PyObject key = keys.__getitem__(i);
130
PyObject value = pyDict.get(key);
131
backToJavaMap.put(key.toString(), value.__tojava__(Object.class));
132
}
133
```
134
135
## Java Object Access from Python
136
137
### Accessing Java Objects in Python Code
138
139
```java
140
PythonInterpreter interp = new PythonInterpreter();
141
142
// Make Java objects available to Python
143
ArrayList<String> javaList = new ArrayList<>();
144
javaList.add("item1");
145
javaList.add("item2");
146
interp.set("java_list", javaList);
147
148
// Access Java methods from Python
149
interp.exec("""
150
print("Java list size:", java_list.size())
151
java_list.add("item3")
152
for item in java_list:
153
print("Item:", item)
154
""");
155
156
interp.close();
157
```
158
159
### Java Class Access
160
161
```java
162
PythonInterpreter interp = new PythonInterpreter();
163
164
// Import Java classes
165
interp.exec("""
166
from java.util import ArrayList, HashMap
167
from java.lang import System
168
169
# Create Java objects
170
list = ArrayList()
171
list.add("Hello")
172
list.add("World")
173
174
map = HashMap()
175
map.put("key1", "value1")
176
map.put("key2", "value2")
177
178
# Call Java static methods
179
System.out.println("From Python: " + str(list))
180
""");
181
182
interp.close();
183
```
184
185
## Python Object Proxy Classes
186
187
Jython provides proxy classes for seamless Java-Python integration.
188
189
### JavaProxyList
190
191
```java { .api }
192
public class JavaProxyList extends PySequenceList implements List {
193
public JavaProxyList(List list);
194
195
// Implements both Python sequence protocol and Java List interface
196
public boolean add(Object o);
197
public void add(int index, Object element);
198
public boolean remove(Object o);
199
public Object remove(int index);
200
public Object get(int index);
201
public Object set(int index, Object element);
202
public int size();
203
public boolean isEmpty();
204
public void clear();
205
}
206
```
207
208
### JavaProxyMap
209
210
```java { .api }
211
public class JavaProxyMap extends AbstractDict implements Map {
212
public JavaProxyMap(Map map);
213
214
// Implements both Python mapping protocol and Java Map interface
215
public Object put(Object key, Object value);
216
public Object get(Object key);
217
public Object remove(Object key);
218
public boolean containsKey(Object key);
219
public Set keySet();
220
public Collection values();
221
public Set entrySet();
222
public int size();
223
public boolean isEmpty();
224
public void clear();
225
}
226
```
227
228
### Usage Examples
229
230
```java
231
// Wrap Java collections for Python use
232
List<String> javaList = new ArrayList<>();
233
JavaProxyList proxyList = new JavaProxyList(javaList);
234
235
PythonInterpreter interp = new PythonInterpreter();
236
interp.set("proxy_list", proxyList);
237
238
interp.exec("""
239
# Use as Python list
240
proxy_list.append("Hello")
241
proxy_list.append("World")
242
print("Length:", len(proxy_list))
243
for item in proxy_list:
244
print(item)
245
""");
246
247
// Changes are reflected in original Java list
248
System.out.println("Java list: " + javaList);
249
250
interp.close();
251
```
252
253
## Method Invocation
254
255
### Calling Python Functions from Java
256
257
```java
258
PythonInterpreter interp = new PythonInterpreter();
259
260
// Define Python function
261
interp.exec("""
262
def greet(name, age=None):
263
if age:
264
return f"Hello, {name}! You are {age} years old."
265
else:
266
return f"Hello, {name}!"
267
""");
268
269
// Get function object
270
PyObject greetFunc = interp.get("greet");
271
272
// Call with positional arguments
273
PyObject result1 = greetFunc.__call__(new PyObject[]{Py.newString("Alice")});
274
System.out.println(result1); // Hello, Alice!
275
276
// Call with keyword arguments
277
PyObject result2 = greetFunc.__call__(
278
new PyObject[]{Py.newString("Bob"), Py.newInteger(30)},
279
new String[]{"name", "age"}
280
);
281
System.out.println(result2); // Hello, Bob! You are 30 years old.
282
283
interp.close();
284
```
285
286
### Calling Java Methods from Python
287
288
```java
289
PythonInterpreter interp = new PythonInterpreter();
290
291
// Define Java class with methods
292
class Calculator {
293
public static int add(int a, int b) {
294
return a + b;
295
}
296
297
public int multiply(int a, int b) {
298
return a * b;
299
}
300
}
301
302
// Make Java class available
303
interp.set("Calculator", Calculator.class);
304
interp.set("calc_instance", new Calculator());
305
306
interp.exec("""
307
# Call static method
308
result1 = Calculator.add(5, 3)
309
print("5 + 3 =", result1)
310
311
# Call instance method
312
result2 = calc_instance.multiply(4, 7)
313
print("4 * 7 =", result2)
314
""");
315
316
interp.close();
317
```
318
319
## Exception Integration
320
321
### Python Exceptions in Java
322
323
```java
324
PythonInterpreter interp = new PythonInterpreter();
325
326
try {
327
interp.exec("raise ValueError('Something went wrong')");
328
} catch (PyException e) {
329
// Check exception type
330
if (e.match(Py.ValueError)) {
331
System.out.println("Caught ValueError: " + e.value);
332
}
333
334
// Get exception details
335
PyObject excType = e.type;
336
PyObject excValue = e.value;
337
PyTraceback traceback = e.traceback;
338
339
System.out.println("Exception type: " + excType);
340
System.out.println("Exception value: " + excValue);
341
}
342
343
interp.close();
344
```
345
346
### Java Exceptions in Python
347
348
```java
349
class RiskyClass {
350
public static void riskyMethod() throws IOException {
351
throw new IOException("File not found");
352
}
353
}
354
355
PythonInterpreter interp = new PythonInterpreter();
356
interp.set("RiskyClass", RiskyClass.class);
357
358
interp.exec("""
359
try:
360
RiskyClass.riskyMethod()
361
except Exception as e:
362
print("Caught Java exception:", type(e).__name__)
363
print("Message:", str(e))
364
""");
365
366
interp.close();
367
```
368
369
## Advanced Integration Patterns
370
371
### Custom Type Adapters
372
373
Jython provides adapter mechanisms for custom type conversion:
374
375
```java { .api }
376
public interface ClassicPyObjectAdapter {
377
public Object adapt(PyObject o);
378
public PyObject adapt(Object o);
379
public boolean canAdapt(Object o);
380
}
381
382
public interface ExtensiblePyObjectAdapter {
383
public Object adapt(PyObject o);
384
public PyObject adapt(Object o);
385
public boolean canAdapt(Object o);
386
}
387
```
388
389
### Bean Property Access
390
391
Java beans can be accessed using Python attribute syntax:
392
393
```java
394
class Person {
395
private String name;
396
private int age;
397
398
public String getName() { return name; }
399
public void setName(String name) { this.name = name; }
400
public int getAge() { return age; }
401
public void setAge(int age) { this.age = age; }
402
}
403
404
PythonInterpreter interp = new PythonInterpreter();
405
interp.set("person", new Person());
406
407
interp.exec("""
408
# Access bean properties as Python attributes
409
person.name = "Alice"
410
person.age = 30
411
412
print(f"Name: {person.name}")
413
print(f"Age: {person.age}")
414
""");
415
416
interp.close();
417
```
418
419
### Iterator Integration
420
421
Java iterables work seamlessly with Python iteration:
422
423
```java
424
List<String> items = Arrays.asList("apple", "banana", "cherry");
425
426
PythonInterpreter interp = new PythonInterpreter();
427
interp.set("items", items);
428
429
interp.exec("""
430
# Iterate over Java list using Python syntax
431
for item in items:
432
print("Item:", item)
433
434
# Use with Python list comprehensions
435
upper_items = [item.upper() for item in items]
436
print("Upper case:", upper_items)
437
""");
438
439
interp.close();
440
```
441
442
## Performance Considerations
443
444
### Minimizing Conversions
445
446
```java
447
// Avoid repeated conversions
448
// Bad:
449
for (int i = 0; i < 1000; i++) {
450
PyObject pyInt = Py.java2py(i);
451
// use pyInt
452
}
453
454
// Better:
455
PyObject[] pyInts = new PyObject[1000];
456
for (int i = 0; i < 1000; i++) {
457
pyInts[i] = Py.java2py(i);
458
}
459
```
460
461
### Reusing Objects
462
463
```java
464
// Reuse common objects
465
PyString separator = Py.newString(",");
466
PyList result = Py.newList();
467
468
for (String item : items) {
469
if (result.__len__() > 0) {
470
result.append(separator);
471
}
472
result.append(Py.java2py(item));
473
}
474
```
475
476
## Thread Safety
477
478
Type conversion operations are generally thread-safe, but be careful with:
479
480
- Shared PyObject instances
481
- Concurrent access to mutable Python objects
482
- System state modifications
483
484
```java
485
// Thread-safe pattern
486
public class ThreadSafeConverter {
487
private static final ThreadLocal<PythonInterpreter> INTERPRETER =
488
ThreadLocal.withInitial(() -> PythonInterpreter.threadLocalStateInterpreter(null));
489
490
public PyObject convert(Object javaObj) {
491
return Py.java2py(javaObj);
492
}
493
494
public Object convert(PyObject pyObj, Class<?> targetClass) {
495
return pyObj.__tojava__(targetClass);
496
}
497
}
498
```