Java es el lenguaje que llevó la máquina virtual y la recolección de basura al software empresarial del mundo entero. Treinta años después sigue moviendo los sistemas de banca, seguros y comercio de media Europa — y, después de una década de fama de lento y verboso, ha cambiado más en los últimos seis años que en los veinte anteriores.
🎯 Por qué está en este programa
Java es uno de los diez lenguajes del núcleo y el representante de la familia JVM (Atlas): quien entiende la versión Java de una clase reconoce después Kotlin, Scala, Groovy y —con más esfuerzo— Clojure, porque los cuatro compilan al mismo bytecode y comparten biblioteca.
Y aporta al programa los conceptos de máquina virtual con JIT (clases 125 y 126), recolección de basura generacional (clase 131) y orientación a objetos nominal con interfaces (clase 112), que son los que definieron la práctica de la industria durante veinte años.
| Año | 1995; 5 con genéricos (2004); 8 con lambdas (2014); cada 6 meses desde 2017 |
| Autoría | James Gosling y equipo, Sun Microsystems (hoy Oracle) |
| Familia | JVM; sintaxis de C, semántica influida por Smalltalk y Objective-C |
| Paradigma | Orientado a objetos con clases; funcional desde Java 8 |
| Tipado | Estático, nominal y fuerte; con genéricos por borrado |
| Memoria | Recolección de basura; varios recolectores intercambiables |
| Ejecución | Bytecode sobre la JVM, con JIT de dos niveles; también AOT con GraalVM |
| Estado | 🟢 Dominante en sistemas empresariales y en el ecosistema de datos |
En 1991, Sun montó el proyecto Green para hacer software de electrodomésticos: un mando a distancia inteligente. James Gosling diseñó un lenguaje llamado Oak —por un roble que veía desde su ventana— con dos requisitos que resultaron proféticos: portabilidad entre chips distintos y seguridad, porque el código iba a viajar.
El mercado de la televisión interactiva no llegó, pero en 1995 llegó la web, y Sun reposicionó el lenguaje como Java, con el eslogan "write once, run anywhere" y los applets en el navegador. Los applets murieron; la máquina virtual sobrevivió y ganó.
Los hitos que lo formaron:
enum, for-each.try-with-resources (clase 132), NIO.2.Stream — el cambio más grande de su historia, que llevó lo
funcional al lenguaje empresarial (clase 115).Y por el camino, el juicio Oracle contra Google sobre las APIs de Java —resuelto en 2021 a favor del uso legítimo— definió jurisprudencia sobre si una interfaz de programación se puede copiar.
Java es el sitio donde mejor se ve el compromiso central de las clases 125 y 126:
Compilar a bytecode y ejecutarlo en una máquina virtual con JIT da:
+ portabilidad real entre sistemas y arquitecturas
+ optimización con información de EJECUCIÓN, que un compilador estático no tiene
+ recolección de basura, seguridad de memoria y verificación del bytecode
− arranque más lento y consumo de memoria mayor
− y pausas del recolector, que en latencia baja importan (clase 152)
El JIT con información de ejecución merece el detalle, porque es contraintuitivo: la JVM puede generar código más rápido que un compilador estático en ciertos casos, porque sabe qué rama se toma siempre y qué tipo llega de verdad a un método polimórfico, y compila especializando —con una comprobación de guarda por si cambia—.
Es exactamente la caché de envío en línea que se inventó en Smalltalk y en Self (clase 152), y es la razón por la que el despacho dinámico dejó de ser caro.
Y el otro concepto que Java llevó a la industria es el de la clase 112: la interfaz como contrato sin implementación, con herencia simple de clases y múltiple de interfaces — la respuesta al problema del diamante que C++ tiene abierto.
var para inferencia local, y ficheros de una sola clase ejecutables sin main ceremonioso.javac Main.java && java Main < entrada.txt # el camino de la clase 041
java Main.java # desde Java 11: sin compilar antes
mvn verify # o: gradle build (clase 143)
java -jar app.jar
native-image -jar app.jar # GraalVM: binario nativo (clase 174)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] p = br.readLine().trim().split("\\s+");
// Tipado estático nominal: cada valor declara su tipo.
final double precioUnitario = Double.parseDouble(p[0]);
final int cantidad = Integer.parseInt(p[1]);
final double descuento = Double.parseDouble(p[2]);
double subtotal = precioUnitario * cantidad;
double total = subtotal * (1 - descuento);
System.out.printf(Locale.US, "Total: %.2f%n", total);
}
}
Lo que hay que ver, comparando con las otras fichas.
final sí es una constante, a diferencia de la convención de mayúsculas de
Python (clase 041) — aunque final sobre una referencia solo fija el nombre, no
el objeto (clase 102).Locale.US no es decorativo: sin él, en una máquina con configuración española, %.2f
imprimiría 27000,00 con coma. Es la misma trampa que CultureInfo.InvariantCulture en
C# y VB.NET, y una de las causas más frecuentes de que una prueba pase en
local y falle en el servidor (clase 147).int y double son primitivos, no objetos: Java tiene dos mundos de tipos, y el
autoboxing entre ellos cuesta memoria y tiempo (clase 128). Es una de las cosas que Project Valhalla
está en camino de resolver.⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Kotlin · Scala · Groovy · Clojure · C# · Smalltalk