java2py
Traductor de Java a Python pensado para estudiar: tomas el código de un libro de estructuras de datos y algoritmos escrito en Java y obtienes el mismo programa en Python, legible y con las construcciones que usaría alguien que programa en Python.
- Sin IA. Analiza el Java con un parser real (tree-sitter) y aplica reglas fijas: la misma entrada siempre produce la misma salida.
- Acepta lo que le pegues: un archivo completo, una clase, uno o varios métodos, sentencias sueltas o una sola expresión.
- No inventa. Lo que no sabe traducir queda como comentario
# TODO(java2py): ...con el Java original, y además se informa como aviso.
Instalación
pip install java2py
Requiere Python 3.10 o superior.
Uso desde la terminal
java2py Pila.java # muestra el Python en pantalla
java2py Pila.java -o pila.py # lo guarda en un archivo
java2py capitulo3/ -o capitulo3_py/ # traduce todos los .java de una carpeta
java2py -c "int mid = (lo + hi) / 2;" # un fragmento
cat Pila.java | java2py - # desde la entrada estándar
java2py -i # modo interactivo
Opciones: --no-type-hints, --no-fstrings, --no-main, -q (sin avisos).
También funciona como python -m java2py.
Uso desde Python
from java2py import translate, translate_detailed, translate_file
print(translate("int doble(int x) { return x * 2; }"))
# def doble(x: int) -> int:
# return x * 2
resultado = translate_detailed(codigo_java)
print(resultado.code) # el Python generado
print(resultado.warnings) # lo que conviene revisar a mano
translate_file("Pila.java", "pila.py")
Ejemplo
public class Busqueda {
static int binaria(int[] arr, int objetivo) {
int lo = 0, hi = arr.length - 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (arr[mid] == objetivo) return mid;
else if (arr[mid] < objetivo) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
public static void main(String[] args) {
int[] datos = {1, 3, 5, 7, 9};
System.out.println("Posición: " + binaria(datos, 7));
}
}
import sys
class Busqueda:
@staticmethod
def binaria(arr: list[int], objetivo: int) -> int:
lo = 0
hi = len(arr) - 1
while lo <= hi:
mid = (lo + hi) // 2
if arr[mid] == objetivo:
return mid
elif arr[mid] < objetivo:
lo = mid + 1
else:
hi = mid - 1
return -1
@staticmethod
def main(args: list[str]) -> None:
datos = [1, 3, 5, 7, 9]
print(f"Posición: {Busqueda.binaria(datos, 7)}")
if __name__ == "__main__":
Busqueda.main(sys.argv[1:])
Qué traduce
| Java | Python |
|---|---|
Clases, herencia, super, clases abstractas e interfaces |
class, ABC y @abstractmethod |
| Campos y constructores | __init__ con self.campo = ... |
static (métodos y campos) |
@staticmethod y atributos de clase |
| Sobrecarga de métodos y constructores | una función que elige la versión según los argumentos |
toString, equals, hashCode, compareTo |
__str__, __eq__, __hash__, compareTo + __lt__ |
enum, record |
Enum, @dataclass(frozen=True) |
| Clases anidadas e internas | clases al nivel del módulo (las internas reciben la instancia externa) |
Iterable / Iterator propios |
__iter__ / __next__ para poder usar for |
for con contador, for-each, while, do-while |
for ... in range(...), for ... in, while |
switch (clásico y con ->) |
match / case |
try / catch / finally, throw, try-with-resources |
try / except / finally, raise, with |
Arreglos (new int[n], new int[n][m], {1, 2}) |
listas |
ArrayList, LinkedList, Stack |
list |
Queue, Deque, ArrayDeque |
collections.deque |
PriorityQueue |
lista + heapq |
HashMap, HashSet (y variantes) |
dict, set |
String, char, StringBuilder |
str (con ord()/chr() donde hace falta) |
"a" + x + "b" |
f-strings |
System.out.println/print/printf, String.format |
print, operador % |
Math, Integer, Character, Arrays, Collections, Objects, BigInteger |
math, funciones integradas, métodos de list/str |
| Lambdas y referencias a métodos | lambda, funciones |
| Excepciones de Java | la excepción de Python más cercana (IllegalArgumentException → ValueError...) |
| Javadoc y comentarios | docstrings y comentarios # |
Los nombres se conservan tal cual (getNombre, insertarAlFinal) para que puedas seguir el
libro línea por línea. Solo cambian cuando chocan con Python: in → in_, una variable
max → max_, y un campo que se llama igual que un método (size y size()) → _size.
Diferencias entre Java y Python que debes conocer
La traducción busca el Python más cercano, pero los lenguajes no se comportan igual en todo:
- División y módulo con negativos.
-7 / 2es-3en Java y-7 // 2es-4en Python (y-7 % 2da-1contra1). Con números no negativos el resultado es idéntico. - Enteros sin límite. En Python no hay desbordamiento de
int/long. Código que depende de él (algunas funciones hash,>>>) da resultados distintos. - Texto que se imprime.
true/false/nullse imprimen comoTrue/False/None, y unHashMapcomo{'a': 1}en vez de{a=1}. StringBuilderse traduce comostr, que es inmutable. Si un método recibe unStringBuildery lo modifica, quien lo llamó no verá el cambio.- Colas vacías y claves ausentes.
queue.poll()ostack.peek()sobre una estructura vacía devuelvennullen Java; en Python lanzanIndexError.map.get(k)sí devuelveNone. null. Llamar un método sobreNonelanzaAttributeError, noNullPointerException.Scanner.nextInt()se traduce comoint(input()), que lee una línea completa.TreeMap/TreeSetse traducen comodict/set, que no mantienen orden por clave.PriorityQueuecon comparador.heapqsiempre es un min-heap; se deja unTODO.
Lo que no traduce
Queda como # TODO(java2py) con el código original: streams (.stream(), .forEach),
clases anónimas, break/continue con etiqueta, hilos y concurrencia, reflexión y
bibliotecas externas. Los import de Java se descartan.
Si un archivo define dos clases anidadas con el mismo nombre (dos Node distintos), en Python
quedan al mismo nivel y chocan; se avisa cuando ocurre.
Desarrollo
git clone https://github.com/maosuarez/java2py && cd java2py
pip install -e ".[dev]"
pytest
tests/cases/ contiene programas Java completos junto con la salida real que producen en
Java (.expected); las pruebas los traducen, ejecutan el Python y comparan ambas salidas.
Publicar en PyPI
La publicación es automática con Trusted Publishing: al crear un Release en GitHub, el
flujo .github/workflows/publish.yml corre las pruebas, construye el paquete y lo sube a PyPI.
- Cambia
__version__ensrc/java2py/__init__.py. - Crea un Release en GitHub con esa versión (por ejemplo
v0.1.0).
Licencia
MIT.
Metadata
Release files for java2py 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| java2py-0.1.0.tar.gz | 57.3 kB | With provenance | Details for java2py-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| java2py-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for java2py-0.1.0-py3-none-any.whl |
Total release size: 104.1 kB
Release files / java2py-0.1.0.tar.gz
| Download URL | java2py-0.1.0.tar.gz |
|---|---|
| Size | 57.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
24ac088ab16cf01f3a56b0992c34c8a9ded0cc1ca80079e3d4a9869d60f3958e
|
|
BLAKE2b-256 checksum How to use checksums |
075d43c3e5bbb15e3529b58f919bc4ea1d1379e0d423d6fecb235d2f3e7bd22d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / java2py-0.1.0-py3-none-any.whl
| Download URL | java2py-0.1.0-py3-none-any.whl |
|---|---|
| Size | 46.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fdff58c4e0048c454ae2ea1911650af103c0c928e6b9b2315e63407a078d9343
|
|
BLAKE2b-256 checksum How to use checksums |
f29202cdb461c9d814df2357c6f87f6f224f77c7b0a0ebdffc40cc46863e8588
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logSecurity for java2py 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for java2py-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.