Cómo aprobar una entrevista de Java: las mejores preguntas de nivel avanzado
Una entrevista para un puesto de desarrollador Java de nivel avanzado (Middle/Senior) no es solo una comprobación de sintaxis. Los entrevistadores quieren ver un conocimiento profundo del funcionamiento interno de la JVM, el multihilo, los algoritmos del recolector de basura y los matices de la biblioteca estándar. En este artículo, analizaremos las preguntas más frecuentes y difíciles que te ayudarán a superar con confianza una entrevista técnica.
1. Multihilo y sincronización: de volatile a Lock
Una entrevista avanzada de Java casi siempre comienza con preguntas sobre multihilo. No solo necesitas conocer la palabra clave synchronized, sino también entender cómo funcionan volatile, AtomicInteger, ReentrantLock y qué es happens-before.
Pregunta: ¿Cuál es la diferencia entre synchronized y ReentrantLock?
La diferencia clave es la flexibilidad. synchronized es un bloqueo a nivel de monitor de objeto. ReentrantLock proporciona capacidades avanzadas: la posibilidad de interrumpir la espera de un hilo (lockInterruptibly()), intentar adquirir el bloqueo sin bloquearse (tryLock()), y soporte para múltiples condiciones (Condition).
// Ejemplo de uso de ReentrantLock con Conditionimport java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.Condition;
public class BlockingQueueExample { private final ReentrantLock lock = new ReentrantLock(); private final Condition notFull = lock.newCondition(); private final Condition notEmpty = lock.newCondition(); private final Object[] items = new Object[10]; private int putIndex, takeIndex, count;
public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) { notFull.await(); // espera hasta que haya espacio } items[putIndex] = x; if (++putIndex == items.length) putIndex = 0; count++; notEmpty.signal(); // señala que hay un elemento } finally { lock.unlock(); } }
public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) { notEmpty.await(); // espera hasta que haya un elemento } Object x = items[takeIndex]; if (++takeIndex == items.length) takeIndex = 0; count--; notFull.signal(); // señala que hay espacio libre return x; } finally { lock.unlock(); } }}Pregunta: ¿Cómo funciona la palabra clave volatile?
volatile garantiza que la lectura y escritura de una variable se realice directamente desde la memoria principal, evitando la caché del procesador. Esto asegura la visibilidad de los cambios para todos los hilos, pero no garantiza la atomicidad (por ejemplo, el incremento count++ aún requiere sincronización).
También es importante recordar happens-before: la escritura en una variable volatile ocurre antes de cualquier lectura posterior de la misma variable desde otro hilo.
2. Java Memory Model (JMM) y Garbage Collector
Comprender cómo la JVM gestiona la memoria es un requisito obligatorio para un desarrollador Senior. Los entrevistadores suelen preguntar sobre las diferentes generaciones (Young/Old Generation), los tipos de recolectores de basura y la configuración de la JVM.
Pregunta: ¿Qué tipos de Garbage Collector existen en Java 17?
Java moderno (17+) soporta varios GC:
- G1GC (Garbage First) — GC por defecto. Divide el heap en regiones y recolecta basura en las regiones con mayor cantidad de objetos muertos.
- ZGC (Z Garbage