0
# Manual Class Definition
1
2
Manual class definition provides precise control over Java class access by explicitly declaring which methods and fields to expose. This approach offers better performance than autoclass and enables custom behavior, but requires knowledge of Java class signatures.
3
4
## Capabilities
5
6
### Base Classes
7
8
Foundation classes for creating manual Java wrapper classes.
9
10
```python { .api }
11
class JavaClass:
12
"""
13
Base class for manually defined Java class wrappers.
14
15
All manual Java class wrappers must inherit from this class and use
16
MetaJavaClass as their metaclass.
17
"""
18
19
class MetaJavaClass(type):
20
"""
21
Metaclass for Java class wrappers that handles method and field binding.
22
23
Automatically processes class definitions to bind Java methods and fields
24
to Python wrapper classes during class creation.
25
"""
26
27
class MetaJavaBase(type):
28
"""Base metaclass for Java class wrappers."""
29
```
30
31
### Method Wrappers
32
33
Wrapper classes for binding Java methods to Python classes.
34
35
```python { .api }
36
def JavaMethod(signature: str, varargs: bool = False) -> callable:
37
"""
38
Create wrapper for Java instance method.
39
40
Args:
41
signature: JNI method signature (e.g., '(Ljava/lang/String;)V')
42
varargs: Whether method accepts variable arguments
43
44
Returns:
45
Callable that can be assigned to class attribute. The returned
46
method object has a signatures() method for introspection.
47
"""
48
49
def JavaStaticMethod(signature: str, varargs: bool = False) -> callable:
50
"""
51
Create wrapper for Java static method.
52
53
Args:
54
signature: JNI method signature (e.g., '()Ljava/lang/String;')
55
varargs: Whether method accepts variable arguments
56
57
Returns:
58
Callable that can be assigned to class attribute
59
"""
60
61
def JavaMultipleMethod(signatures: list) -> callable:
62
"""
63
Create wrapper for overloaded Java methods.
64
65
Args:
66
signatures: List of (signature, is_static, varargs) tuples
67
68
Returns:
69
Callable that dispatches to appropriate overload based on arguments
70
"""
71
```
72
73
### Field Wrappers
74
75
Wrapper classes for binding Java fields to Python classes.
76
77
```python { .api }
78
def JavaField(signature: str) -> property:
79
"""
80
Create wrapper for Java instance field.
81
82
Args:
83
signature: JNI field type signature (e.g., 'Ljava/lang/String;')
84
85
Returns:
86
Property that can be assigned to class attribute
87
"""
88
89
def JavaStaticField(signature: str) -> property:
90
"""
91
Create wrapper for Java static field.
92
93
Args:
94
signature: JNI field type signature (e.g., 'I' for int)
95
96
Returns:
97
Property that can be assigned to class attribute
98
"""
99
```
100
101
### Core Java Object Wrapper
102
103
Base wrapper for individual Java objects.
104
105
```python { .api }
106
class JavaObject:
107
"""
108
Base wrapper class for individual Java objects.
109
110
Provides low-level access to Java objects with automatic memory management
111
and method dispatch. Typically not used directly - JavaClass is preferred.
112
"""
113
```
114
115
### Enhanced Python-Java Class
116
117
Enhanced base class with built-in Java method implementations.
118
119
```python { .api }
120
class PythonJavaClass(JavaClass):
121
"""
122
Enhanced JavaClass with built-in Java method implementations.
123
124
Can be used to create Python classes that implement Java interfaces
125
by setting __javainterfaces__ class attribute.
126
127
Automatically provides standard Java object methods like hashCode(),
128
toString(), and equals() with Python-compatible implementations.
129
"""
130
131
def hashCode() -> int:
132
"""Java-compatible hash code based on Python object id."""
133
134
def toString() -> str:
135
"""Java-compatible string representation using Python repr."""
136
137
def equals(other: object) -> bool:
138
"""Java-compatible equality check using hash codes."""
139
140
def invoke(self, method: str, *args) -> any:
141
"""Invoke Java method by name with arguments."""
142
143
def _invoke(self, method: str, *args) -> any:
144
"""Internal method invocation handler."""
145
```
146
147
### Decorator for Method Binding
148
149
Decorator for binding Java methods to Python methods.
150
151
```python { .api }
152
def java_method(signature: str, name: str = None, varargs: bool = False) -> callable:
153
"""
154
Decorator for binding Java methods to Python methods.
155
156
Args:
157
signature: JNI method signature
158
name: Java method name (defaults to Python method name)
159
varargs: Whether method accepts variable arguments
160
161
Returns:
162
Decorator function for Python methods
163
"""
164
```
165
166
**Usage Examples:**
167
168
### Basic Manual Class Definition
169
170
```python
171
from jnius import JavaClass, MetaJavaClass, JavaMethod, JavaStaticMethod, JavaField
172
173
class String(JavaClass, metaclass=MetaJavaClass):
174
__javaclass__ = 'java/lang/String'
175
176
# Constructor signatures
177
__javaconstructor__ = [
178
('()V', False), # Default constructor
179
('(Ljava/lang/String;)V', False), # String constructor
180
('([C)V', False), # char array constructor
181
]
182
183
# Instance methods
184
length = JavaMethod('()I')
185
charAt = JavaMethod('(I)C')
186
substring = JavaMultipleMethod([
187
('(I)Ljava/lang/String;', False, False),
188
('(II)Ljava/lang/String;', False, False),
189
])
190
toUpperCase = JavaMethod('()Ljava/lang/String;')
191
toLowerCase = JavaMethod('()Ljava/lang/String;')
192
equals = JavaMethod('(Ljava/lang/Object;)Z')
193
194
# Static methods
195
valueOf = JavaMultipleMethod([
196
('(I)Ljava/lang/String;', True, False),
197
('(F)Ljava/lang/String;', True, False),
198
('(D)Ljava/lang/String;', True, False),
199
('(Ljava/lang/Object;)Ljava/lang/String;', True, False),
200
])
201
202
# Usage
203
text = String('Hello World')
204
print(text.length()) # 11
205
print(text.toUpperCase()) # HELLO WORLD
206
print(String.valueOf(42)) # "42"
207
```
208
209
### Class with Fields
210
211
```python
212
from jnius import JavaClass, MetaJavaClass, JavaStaticField, JavaField
213
214
class System(JavaClass, metaclass=MetaJavaClass):
215
__javaclass__ = 'java/lang/System'
216
217
# Static fields
218
out = JavaStaticField('Ljava/io/PrintStream;')
219
err = JavaStaticField('Ljava/io/PrintStream;')
220
221
# Static methods
222
currentTimeMillis = JavaStaticMethod('()J')
223
getProperty = JavaStaticMethod('(Ljava/lang/String;)Ljava/lang/String;')
224
225
# Usage
226
System.out.println('Hello World')
227
version = System.getProperty('java.version')
228
timestamp = System.currentTimeMillis()
229
```
230
231
### Using Java Method Decorator
232
233
```python
234
from jnius import PythonJavaClass, MetaJavaClass, java_method
235
236
class MyJavaClass(PythonJavaClass, metaclass=MetaJavaClass):
237
__javaclass__ = 'com/example/MyClass'
238
239
@java_method('(Ljava/lang/String;)V')
240
def setName(self, name):
241
pass # Implementation handled by decorator
242
243
@java_method('()Ljava/lang/String;')
244
def getName(self):
245
pass # Implementation handled by decorator
246
247
@java_method('(I)I', name='multiply')
248
def multiplyByTwo(self, value):
249
pass # Java method named 'multiply', Python method named 'multiplyByTwo'
250
251
# Usage
252
obj = MyJavaClass()
253
obj.setName('example')
254
name = obj.getName()
255
result = obj.multiplyByTwo(5)
256
```
257
258
### Python-to-Java Interface Implementation
259
260
```python
261
from jnius import PythonJavaClass, MetaJavaClass, java_method
262
263
class MyRunnable(PythonJavaClass, metaclass=MetaJavaClass):
264
__javainterfaces__ = ['java/lang/Runnable']
265
266
@java_method('()V')
267
def run(self):
268
print("Running from Python implementation of Java Runnable!")
269
270
class MyComparator(PythonJavaClass, metaclass=MetaJavaClass):
271
__javainterfaces__ = ['java/util/Comparator']
272
273
@java_method('(Ljava/lang/Object;Ljava/lang/Object;)I')
274
def compare(self, o1, o2):
275
# Custom comparison logic in Python
276
return str(o1).lower() < str(o2).lower()
277
278
# Usage - pass Python objects as Java interfaces
279
from jnius import autoclass
280
281
Thread = autoclass('java.lang.Thread')
282
Arrays = autoclass('java.util.Arrays')
283
284
# Use Python Runnable with Java Thread
285
runnable = MyRunnable()
286
thread = Thread(runnable)
287
thread.start()
288
289
# Use Python Comparator with Java sorting
290
comparator = MyComparator()
291
string_array = Arrays.asList(['Zebra', 'apple', 'Banana'])
292
string_array.sort(comparator)
293
```
294
295
### Method Introspection
296
297
Java method wrappers provide introspection capabilities for examining signatures.
298
299
```python { .api }
300
# Available on JavaMethod, JavaStaticMethod, and JavaMultipleMethod instances
301
def signatures() -> list:
302
"""
303
Get list of method signatures for introspection.
304
305
Returns:
306
List of signature tuples (args, return_type) for the method
307
"""
308
```
309
310
**Usage Examples:**
311
312
```python
313
from jnius import autoclass
314
315
# Automatic introspection with autoclass
316
String = autoclass('java.lang.String')
317
print(String.format.signatures())
318
# Output: [(['java/util/Locale', 'java/lang/String', 'java/lang/Object...'], 'java/lang/String'),
319
# (['java/lang/String', 'java/lang/Object...'], 'java/lang/String')]
320
321
# Manual class introspection
322
class MyString(JavaClass, metaclass=MetaJavaClass):
323
__javaclass__ = 'java/lang/String'
324
325
format = JavaMultipleMethod([
326
('(Ljava/util/Locale;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;', True, True),
327
('(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;', True, True),
328
])
329
330
print(MyString.format.signatures())
331
# Shows available overloads for the format method
332
```
333
334
### Performance Comparison
335
336
Manual class definition offers several advantages over autoclass:
337
338
- **Faster instantiation**: No runtime reflection overhead
339
- **Smaller memory footprint**: Only declared methods and fields are bound
340
- **Type safety**: Explicit signatures catch errors at definition time
341
- **Custom behavior**: Ability to override or extend Java functionality
342
- **Selective exposure**: Choose which methods and fields to expose
343
344
However, manual definition requires:
345
346
- Knowledge of JNI signature format
347
- Manual maintenance when Java classes change
348
- More verbose code compared to autoclass