Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/groovy/how-to-guides/java-classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,29 @@ source = emptyTable(10).update(
sourceMeta = source.meta()
```

## Nested (inner) classes

Java allows users to define classes inside other classes. In Groovy, you access these nested (inner) classes using dot notation — `OuterClass.InnerClass` — which is standard Java syntax.

```groovy order=null test-set=inner-classes-groovy
import io.deephaven.engine.table.impl.util.SyncTableFilter

// Access the Builder inner class of SyncTableFilter using dot notation
def builder = new SyncTableFilter.Builder()
```

You can also import the inner class directly to use it without the outer class qualifier:

```groovy order=null test-set=inner-classes-groovy
import io.deephaven.engine.table.impl.util.SyncTableFilter.Builder

// Use Builder directly after importing
def builder2 = new Builder()
```

> [!NOTE]
> If you load a class dynamically with `Class.forName()`, use `$` as the separator — `OuterClass$InnerClass`. This is the JVM's internal binary class name format. In Groovy source code, always use dot notation.

## Groovy's Java interoperability

One of Groovy's greatest strengths is its seamless interoperability with Java. In Groovy query strings, you can:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/java-classes.md","objects":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/java-classes.md","objects":{}}
54 changes: 48 additions & 6 deletions docs/python/how-to-guides/use-jpy.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import jpy

_JURL = jpy.get_type("java.net.URL")

# the print function is overloaded to print the classpath of the underlying Java type
# the print function is overloaded to print the fully qualified class name of the underlying Java type
print(_JURL)
# the class gets recognized as a Python type, confirming that this is a Python object
print(type(_JURL))
Expand All @@ -64,6 +64,48 @@ help(_JURL)

Check the [Javadoc for `java.net.URL`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/URL.html) to confirm that all of its methods are represented by the Python wrapping.

### Access nested (inner) classes

In Java, inner classes are accessed with dot notation: `OuterClass.InnerClass`. However, [`jpy.get_type`](/core/pydoc/code/jpy.html#jpy.get_type) expects the JVM's internal binary class name, which uses `$` as the separator between outer and inner class names. Using dot notation will fail.

```python should-fail
import jpy

# ❌ Dot notation does not work for inner classes
_JMapEntry = jpy.get_type("java.util.Map.Entry")
```

Use `$` instead:

```python test-set=inner-classes
import jpy

# ✅ Use $ to separate the outer and inner class names
_JMapEntry = jpy.get_type("java.util.Map$Entry")
```

The pattern is: `jpy.get_type("fully.qualified.OuterClass$InnerClass")`. This applies to all levels of nesting — `OuterClass$InnerClass$DeepInner` for classes nested two levels deep.

Here are examples using Deephaven types:

```python test-set=inner-classes
# Builder inner class of SyncTableFilter
_JSyncTableFilterBuilder = jpy.get_type(
"io.deephaven.engine.table.impl.util.SyncTableFilter$Builder"
)

# Builder inner classes of LeaderTableFilter
_JLeaderTableFilterTableBuilder = jpy.get_type(
"io.deephaven.engine.util.LeaderTableFilter$TableBuilder"
)
_JLeaderTableFilterPartitionedTableBuilder = jpy.get_type(
"io.deephaven.engine.util.LeaderTableFilter$PartitionedTableBuilder"
)
```

> [!NOTE]
> The `$`-separated name is the JVM's internal binary class name. You can find it in the Java source or Javadoc — look for `static class InnerClass` inside the outer class definition. The separator is always `$`, never `.`.

## Call methods on Java types

Python code can use Java methods directly. This means you can call any Java function from your Python program.
Expand Down Expand Up @@ -109,9 +151,9 @@ print(float_instance_as_string)
print(type(float_instance_as_string))

# the compareTo method returns -1 if float is less than the argument, 0 if equal, and 1 if greater
less_than_or_grearter_than = float_instance.compareTo(654.321)
print(less_than_or_grearter_than)
print(type(less_than_or_grearter_than))
less_than_or_greater_than = float_instance.compareTo(654.321)
print(less_than_or_greater_than)
print(type(less_than_or_greater_than))

# the equals method returns True if the float is equal to the argument, and False otherwise
are_floats_equal = float_instance.equals(123.456)
Expand Down Expand Up @@ -647,7 +689,7 @@ transformed_t = Table(_j_transformed_t)
## Related documentation

- [Python-Java Boundary](../conceptual/python-java-boundary.md)
- [Jpy Github](https://github.com/jpy-consortium/jpy)
- [Jpy Javadoc](/core/javadoc/io/deephaven/jpy/package-summary.html)
- [jpy GitHub](https://github.com/jpy-consortium/jpy)
- [jpy documentation](https://jpy.readthedocs.io/en/latest/)
- [Jpy Pydoc](/core/pydoc/code/jpy.html#module-jpy)
- [Type signatures](https://docs.oracle.com/en/java/javase/17/docs/specs/jni/types.html)
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"file":"core/docs/how-to-guides/use-jpy.md","objects":{":log":{"type":"Log","data":"Help on class URL:\n\nclass URL(java.lang.Object)\n | Method resolution order:\n | URL\n | java.lang.Object\n | jpy.JType\n | builtins.object\n | \n | Methods defined here:\n | \n | __delattr__(self, name, /)\n | Implement delattr(self, name).\n | \n | __eq__(self, value, /)\n | Return self==value.\n | \n | __ge__(self, value, /)\n | Return self>=value.\n | \n | __getattribute__(self, name, /)\n | Return getattr(self, name).\n | \n | __gt__(self, value, /)\n | Return self>value.\n | \n | __hash__(self, /)\n | Return hash(self).\n | \n | __init__(self, /, *args, **kwargs)\n | Initialize self. See help(type(self)) for accurate signature.\n | \n | __le__(self, value, /)\n | Return self<=value.\n | \n | __lt__(self, value, /)\n | Return self<value.\n | \n | __ne__(self, value, /)\n | Return self!=value.\n | \n | __repr__(self, /)\n | Return repr(self).\n | \n | __setattr__(self, name, value, /)\n | Implement setattr(self, name, value).\n | \n | __str__(self, /)\n | Return str(self).\n | \n | ----------------------------------------------------------------------\n | Static methods defined here:\n | \n | __new__(*args, **kwargs) from builtins.type\n | Create and return a new object. See help(type) for accurate signature.\n | \n | ----------------------------------------------------------------------\n | Data and other attributes defined here:\n | \n | __jinit__ = jpy.JOverloadedMethod(class='java.net.URL', name='__jinit_...\n | \n | equals = jpy.JOverloadedMethod(class='java.net.URL', name='equals', me...\n | \n | getAuthority = jpy.JOverloadedMethod(class='java.net.URL', name='getAu...\n | \n | getClass = jpy.JOverloadedMethod(class='java.net.URL', name='getClass'...\n | \n | getContent = jpy.JOverloadedMethod(class='java.net.URL', name='getCont...\n | \n | getDefaultPort = jpy.JOverloadedMethod(class='java.net.URL', name='get...\n | \n | getFile = jpy.JOverloadedMethod(class='java.net.URL', name='getFile', ...\n | \n | getHost = jpy.JOverloadedMethod(class='java.net.URL', name='getHost', ...\n | \n | getPath = jpy.JOverloadedMethod(class='java.net.URL', name='getPath', ...\n | \n | getPort = jpy.JOverloadedMethod(class='java.net.URL', name='getPort', ...\n | \n | getProtocol = jpy.JOverloadedMethod(class='java.net.URL', name='getPro...\n | \n | getQuery = jpy.JOverloadedMethod(class='java.net.URL', name='getQuery'...\n | \n | getRef = jpy.JOverloadedMethod(class='java.net.URL', name='getRef', me...\n | \n | getUserInfo = jpy.JOverloadedMethod(class='java.net.URL', name='getUse...\n | \n | hashCode = jpy.JOverloadedMethod(class='java.net.URL', name='hashCode'...\n | \n | jclass = java.lang.Class(objectRef=0xffff929dfd72)\n | \n | jclassname = 'java.net.URL'\n | \n | notify = jpy.JOverloadedMethod(class='java.net.URL', name='notify', me...\n | \n | notifyAll = jpy.JOverloadedMethod(class='java.net.URL', name='notifyAl...\n | \n | of = jpy.JOverloadedMethod(class='java.net.URL', name='of', methodCoun...\n | \n | openConnection = jpy.JOverloadedMethod(class='java.net.URL', name='ope...\n | \n | openStream = jpy.JOverloadedMethod(class='java.net.URL', name='openStr...\n | \n | sameFile = jpy.JOverloadedMethod(class='java.net.URL', name='sameFile'...\n | \n | setURLStreamHandlerFactory = jpy.JOverloadedMethod(class='java.net.URL...\n | \n | toExternalForm = jpy.JOverloadedMethod(class='java.net.URL', name='toE...\n | \n | toString = jpy.JOverloadedMethod(class='java.net.URL', name='toString'...\n | \n | toURI = jpy.JOverloadedMethod(class='java.net.URL', name='toURI', meth...\n | \n | wait = jpy.JOverloadedMethod(class='java.net.URL', name='wait', method...\n\n"}}}
{"file":"how-to-guides/use-jpy.md","objects":{":log":{"type":"Log","data":"Help on class URL:\n\nclass URL(java.lang.Object)\n | Method resolution order:\n | URL\n | java.lang.Object\n | jpy.JType\n | builtins.object\n |\n | Methods defined here:\n |\n | __delattr__(self, name, /)\n | Implement delattr(self, name).\n |\n | __eq__(self, value, /)\n | Return self==value.\n |\n | __ge__(self, value, /)\n | Return self>=value.\n |\n | __getattribute__(self, name, /)\n | Return getattr(self, name).\n |\n | __gt__(self, value, /)\n | Return self>value.\n |\n | __hash__(self, /)\n | Return hash(self).\n |\n | __init__(self, /, *args, **kwargs)\n | Initialize self. See help(type(self)) for accurate signature.\n |\n | __le__(self, value, /)\n | Return self<=value.\n |\n | __lt__(self, value, /)\n | Return self<value.\n |\n | __ne__(self, value, /)\n | Return self!=value.\n |\n | __repr__(self, /)\n | Return repr(self).\n |\n | __setattr__(self, name, value, /)\n | Implement setattr(self, name, value).\n |\n | __str__(self, /)\n | Return str(self).\n |\n | ----------------------------------------------------------------------\n | Static methods defined here:\n |\n | __new__(*args, **kwargs)\n | Create and return a new object. See help(type) for accurate signature.\n |\n | ----------------------------------------------------------------------\n | Data and other attributes defined here:\n |\n | __jinit__ = jpy.JOverloadedMethod(class='java.net.URL', name='__jinit_...\n |\n | equals = jpy.JOverloadedMethod(class='java.net.URL', name='equals', me...\n |\n | getAuthority = jpy.JOverloadedMethod(class='java.net.URL', name='getAu...\n |\n | getClass = jpy.JOverloadedMethod(class='java.net.URL', name='getClass'...\n |\n | getContent = jpy.JOverloadedMethod(class='java.net.URL', name='getCont...\n |\n | getDefaultPort = jpy.JOverloadedMethod(class='java.net.URL', name='get...\n |\n | getFile = jpy.JOverloadedMethod(class='java.net.URL', name='getFile', ...\n |\n | getHost = jpy.JOverloadedMethod(class='java.net.URL', name='getHost', ...\n |\n | getPath = jpy.JOverloadedMethod(class='java.net.URL', name='getPath', ...\n |\n | getPort = jpy.JOverloadedMethod(class='java.net.URL', name='getPort', ...\n |\n | getProtocol = jpy.JOverloadedMethod(class='java.net.URL', name='getPro...\n |\n | getQuery = jpy.JOverloadedMethod(class='java.net.URL', name='getQuery'...\n |\n | getRef = jpy.JOverloadedMethod(class='java.net.URL', name='getRef', me...\n |\n | getUserInfo = jpy.JOverloadedMethod(class='java.net.URL', name='getUse...\n |\n | hashCode = jpy.JOverloadedMethod(class='java.net.URL', name='hashCode'...\n |\n | jclass = java.lang.Class(objectRef=0xffff8a46226a)\n |\n | jclassname = 'java.net.URL'\n |\n | notify = jpy.JOverloadedMethod(class='java.net.URL', name='notify', me...\n |\n | notifyAll = jpy.JOverloadedMethod(class='java.net.URL', name='notifyAl...\n |\n | of = jpy.JOverloadedMethod(class='java.net.URL', name='of', methodCoun...\n |\n | openConnection = jpy.JOverloadedMethod(class='java.net.URL', name='ope...\n |\n | openStream = jpy.JOverloadedMethod(class='java.net.URL', name='openStr...\n |\n | sameFile = jpy.JOverloadedMethod(class='java.net.URL', name='sameFile'...\n |\n | setURLStreamHandlerFactory = jpy.JOverloadedMethod(class='java.net.URL...\n |\n | toExternalForm = jpy.JOverloadedMethod(class='java.net.URL', name='toE...\n |\n | toString = jpy.JOverloadedMethod(class='java.net.URL', name='toString'...\n |\n | toURI = jpy.JOverloadedMethod(class='java.net.URL', name='toURI', meth...\n |\n | wait = jpy.JOverloadedMethod(class='java.net.URL', name='wait', method...\n\n"}}}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/use-jpy.md","objects":{":log":{"type":"Log","data":"123.456\n<class 'str'>\n-1\n<class 'int'>\nFalse\n<class 'bool'>\n"}}}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/use-jpy.md","objects":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/use-jpy.md","objects":{}}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"file":"core/docs/how-to-guides/use-jpy.md","objects":{}}
{"file":"how-to-guides/use-jpy.md","objects":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"file":"how-to-guides/use-jpy.md","objects":{":log":{"type":"Log","data":"<class 'java.net.URL'>\n<class 'type'>\n"}}}
Loading