Arma un pequeño ejecutor de pruebas solo con el JDK a partir de una anotación y reflexión, prueba código package-private con –patch-module y distribuye un servicio Java como JAR modular, imagen de runtime de jlink e instalador de jpackage.
El JDK de Java puede llamar y servir HTTP sin bibliotecas. Aprende HttpClient, síncrono y asíncrono, y luego construye un pequeño servicio de tareas en JSON sobre el HttpServer incorporado, con hilos virtuales, códigos de estado correctos y un apagado limpio.
Java puede ejecutar cien mil tareas bloqueantes sobre unos pocos hilos del SO. Mira cómo se montan y desmontan los hilos virtuales, qué los sigue anclando, por qué ScopedValue reemplaza a ThreadLocal y cómo StructuredTaskScope cancela el trabajo que falla.
Los executors de Java ejecutan tus tareas en un pool fijo de hilos y te devuelven un Future. Aprende submit, invokeAll, la cancelación, las cadenas de CompletableFuture, los timeouts, los semáforos y las colas bloqueantes, con una salida que no varía.
Dos hilos de Java que actualizan la misma variable pueden perder escrituras en silencio. Mira por qué count++ es una carrera, cómo la arreglan synchronized, volatile, los atomics y los locks, y cómo forzar y detectar un deadlock.
Dónde guarda Java tus variables y objetos, cómo decide el recolector de basura qué liberar, por qué un programa con recolección de basura igual puede tener fugas o quedarse sin memoria, y cómo el JIT hace el código más rápido cuanto más tiempo corre.
Arma un proyecto Java de dos módulos solo con javac, jar y java. Mira cómo encajan los paquetes, los imports, el classpath, los archivos JAR y module-info.java, y qué agregan Maven y Gradle encima.
Java deja que cualquier referencia sea null, así que un valor ausente puede romper el código lejos de donde se perdió. Objects y Optional hacen visible ese valor ausente, y java.time te obliga a decir qué momento, y en qué ciudad, quieres decir.
Las lambdas de Java convierten un pequeño comportamiento en un valor, y los streams encadenan esos valores en pipelines perezosos. Mira cómo se ejecuta de verdad un pipeline, qué collectors conviene usar y cuándo un bucle simple se lee mejor.
Los genéricos permiten que el compilador revise lo que entra en una lista, una caja o un método, y luego borran esa información antes de que el programa se ejecute. Aprende límites, comodines, PECS y a leer una firma del JDK con programas pequeños.