or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexception-handling.mdindex.mdjava-integration.mdjsr223-scripting.mdpython-execution.mdpython-objects.md

java-integration.mddocs/

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

```