Solución completa de preguntas comunes de entrevistas en Java

📚 Fundamentos de Java

1. ¿Cuáles son las características de Java?

Comprender las características centrales del lenguaje Java

  • Orientado a objetos: Soporta encapsulación, herencia, polimorfismo y otras características
  • Independencia de plataforma: Escribir una vez, ejecutar en cualquier lugar (WORA)
  • Gestión automática de memoria: Mecanismo de recolección de basura que libera memoria automáticamente
  • Soporte multihilo: Mecanismo de hilos incorporado, facilita la programación concurrente
  • Seguridad fuerte: Proporciona verificación de tipos, manejo de excepciones y otros mecanismos de seguridad
  • Características dinámicas: Comprobación de tipos en tiempo de ejecución y carga dinámica

2. ¿Cuál es la diferencia entre JDK, JRE y JVM?

Entender la estructura de tres capas del entorno de ejecución de Java

  • JVM (Máquina Virtual Java): Máquina virtual, computadora abstracta que ejecuta código de bytes, implementa características multiplataforma
  • JRE (Entorno de Ejecución Java): Entorno de ejecución, contiene JVM y bibliotecas de clases necesarias para ejecutar
  • JDK (Kit de Desarrollo Java): Kit de desarrollo, contiene JRE + compilador + herramientas de depuración y otras herramientas de desarrollo
  • Relación de inclusión: JDK > JRE > JVM

3. ¿Qué es código de bytes? ¿Por qué Java puede funcionar en múltiples plataformas?

Comprender profundamente el principio del mecanismo multiplataforma de Java

  • Definición de código de bytes: Código intermedio generado al compilar código fuente Java, extensión de archivo .class
  • Principio de multiplataforma: Código fuente Java → código de bytes → Ejecución por JVM de diferentes plataformas
  • Ventaja: Compilación única, ejecutable en cualquier lugar; los desarrolladores no necesitan reescribir código para diferentes plataformas
  • Proceso de ejecución: El compilador javac compila archivos .java a archivos .class, que luego ejecuta el JVM de cada plataforma

4. ¿Cuáles son los tipos de datos básicos en Java?

Dominar el sistema de tipos de Java

  • Tipo entero: byte (1 byte), short (2 bytes), int (4 bytes), long (8 bytes)
  • Tipo flotante: float (4 bytes), double (8 bytes)
  • Tipo carácter: char (2 bytes, soporta Unicode)
  • Tipo booleano: boolean (1 byte, true/false)
  • Valores por defecto: Entero 0, flotante 0.0, booleano false, char '\\u0000'
  • Clases envoltorio: Integer, Long, Float, Double, Boolean y otros tipos de referencia correspondientes

5. ¿Cuál es la diferencia entre final, finally y finalize?

Distinguir entre tres conceptos similares pero completamente diferentes

  • final (palabra clave): Modificador que impide que una clase sea heredada, método que no puede ser sobrescrito, variable que no puede ser reasignada
  • finally (palabra clave): Bloque de código en try-catch-finally, se ejecuta independientemente de si hay excepción, se usa comúnmente para liberar recursos
  • finalize (método): Método de la clase Object, se invoca antes de que la recolección de basura recolecte el objeto, se usa para limpiar recursos (obsoleto)
  • Escenarios de aplicación: final se usa para control de inmutabilidad, finally se usa para seguridad ante excepciones, finalize ha sido reemplazado por try-with-resources

🎯 Programación Orientada a Objetos

6. ¿Qué es la programación orientada a objetos? ¿Cuáles son las cuatro características principales?

Comprender la filosofía central de la programación orientada a objetos

  • Definición de OOP: Paradigma de programación basado en objetos, enfatiza los atributos y comportamiento de los objetos
  • Cuatro características principales:
  • Abstracción: Extraer características comunes de las cosas, ignorar detalles no esenciales
  • Encapsulación: Ocultar detalles de implementación interna, exponer interfaces necesarias, mejorar la seguridad
  • Herencia: Las subclases heredan atributos y métodos de la clase padre, realizando reutilización de código
  • Polimorfismo: La misma interfaz tiene diferentes implementaciones, vinculación dinámica en tiempo de ejecución

7. ¿Qué es polimorfismo? ¿Cuáles son los métodos de implementación?

Comprender profundamente el mecanismo de polimorfismo de Java

  • Definición de polimorfismo: Un objeto posee múltiples formas, la misma llamada de método tiene diferentes manifestaciones en diferentes objetos
  • Métodos de implementación:
  • Polimorfismo en tiempo de compilación (sobrecarga): Mismo nombre de método, diferentes parámetros, determinado en tiempo de compilación
  • Polimorfismo en tiempo de ejecución (sobrescritura): Referencia de clase padre apunta a objeto de subclase, determinado en tiempo de ejecución
  • Condiciones de polimorfismo en tiempo de ejecución: Herencia, sobrescritura, conversión hacia arriba
  • Ventaja: Aumenta flexibilidad del código y mantenibilidad, soporta programación basada en interfaces

8. ¿Cuál es la diferencia entre interfaz y clase abstracta?

Contrastar dos mecanismos de abstracción

  • Clase abstracta: Modificada con abstract, puede tener métodos abstractos y concretos
  • Interfaz: Definida con interface, los métodos por defecto son public abstract (Java 8+ soporta implementación por defecto)
  • Relación de herencia: Una clase solo puede heredar una clase abstracta, pero puede implementar múltiples interfaces
  • Modificador de acceso: Clase abstracta puede usar private/protected, miembros de interfaz son public por defecto
  • Variables: Clase abstracta tiene variables de instancia, interfaz tiene solo constantes estáticas
  • Escenario de uso: Clase abstracta se usa para compartir código, interfaz define especificaciones

9. ¿Qué es sobrecarga (Overload) y sobrescritura (Override)?

Distinguir entre dos conceptos similares pero diferentes

  • Sobrecarga (Overload):
  • En la misma clase, mismo nombre de método, tipos/cantidad/orden de parámetros diferentes
  • Determinado en tiempo de compilación, es vinculación estática
  • El tipo de retorno puede ser diferente (pero no se puede distinguir solo por tipo de retorno)
  • Sobrescritura (Override):
  • La subclase reimplementa el método de la clase padre, la firma del método es completamente igual
  • Determinado en tiempo de ejecución, es vinculación dinámica
  • El tipo de retorno y excepciones deben ser compatibles

10. ¿Cuáles son los modificadores de acceso? ¿Cuál es su rango de aplicación?

Dominar el mecanismo de control de acceso de Java

  • public: Público, todas las clases pueden acceder
  • protected: Protegido, acceso desde el mismo paquete y subclases
  • default (sin modificador): Predeterminado, acceso desde el mismo paquete
  • private: Privado, solo acceso desde dentro de la clase
  • Comparación de rango de acceso: public > protected > default > private
  • Mejor práctica: Minimizar permisos de acceso, respetar el principio de encapsulación

💾 Gestión de memoria y recolección de basura

11. ¿Cuáles son las estructuras de memoria de Java?

Comprender la asignación de memoria de la JVM

  • Montículo (Heap): Almacena instancias de objetos, compartido por todos los hilos, área principal de recolección de basura, tamaño configurable
  • Pila (Stack): Almacena variables locales y llamadas de métodos, cada hilo tiene su propia pila, libera memoria automáticamente
  • Área de métodos (Method Area): Almacena información de estructura de clases, grupo de constantes en tiempo de ejecución, variables estáticas, compartido por todos los hilos
  • Contador de programas: Registra la dirección de instrucción de código de bytes que ejecuta actualmente el hilo
  • Pila de métodos nativos: Ejecuta métodos nativos (código C/C++)

12. ¿Qué es la recolección de basura? ¿Cuáles son los algoritmos de recolección de basura?

Comprender profundamente el mecanismo GC

  • Definición de recolección de basura: Recuperar automáticamente memoria ocupada por objetos que ya no se usan
  • Principales algoritmos:
  • Marcar-limpiar: Marcar objetos vivos, limpiar basura, produce fragmentación
  • Algoritmo de copia: Dividir en dos bloques de memoria, durante la limpieza copiar objetos vivos, sin fragmentación pero desperdicia memoria
  • Marcar-compactar: Marcar y luego compactar para reorganizar, sin fragmentación pero rendimiento más bajo
  • Algoritmo generacional: Los objetos se dividen en generación nueva y generación antigua, diferentes generaciones usan diferentes estrategias
  • Ventaja: Gestión automática de memoria, evita fugas de memoria

13. ¿Cuál es la diferencia entre montículo y pila?

Contrastar dos áreas importantes de memoria

  • Contenido almacenado: Montículo almacena objetos, pila almacena tipos básicos y referencias
  • Hilos: Montículo compartido por todos los hilos, cada hilo tiene su propia pila
  • Gestión: Montículo gestionado por recolector de basura, pila libera automáticamente
  • Tamaño: Montículo generalmente más grande, pila relativamente más pequeña
  • Rendimiento: Asignación en pila es rápida, asignación en montículo es relativamente lenta
  • Excepciones: Desbordamiento de montículo OutOfMemoryError, desbordamiento de pila StackOverflowError

14. ¿Qué es una fuga de memoria? ¿Cómo evitarla?

Reconocer problemas comunes de memoria

  • Definición de fuga de memoria: La memoria solicitada por el programa no se puede liberar, ocupando memoria durante mucho tiempo
  • Causas comunes:
  • Objetos de larga vida útil hacen referencia a objetos de corta vida útil
  • Los objetos en colecciones no se limpian a tiempo
  • Los escuchadores o devoluciones de llamada no se cancelan
  • Las colecciones estáticas crecen indefinidamente
  • Métodos para evitar: Liberar referencias a tiempo, usar try-with-resources, verificar el uso de memoria regularmente

15. ¿Qué son referencias fuertes, referencias débiles, referencias suaves y referencias fantasma?

Comprender los cuatro tipos de referencias de Java

  • Referencias fuertes: Referencias ordinarias, los objetos no se recopilan hasta que no hay referencias fuertes
  • Referencias suaves (SoftReference): Se recopilan cuando hay insuficiencia de memoria, se usan para caché
  • Referencias débiles (WeakReference): Se recopilan en el siguiente GC, se usan en WeakHashMap
  • Referencias fantasma (PhantomReference): Se pueden recopilar en cualquier momento, deben usarse con cola de referencias, se usan para rastrear recopilación de objetos
  • Prioridad de recopilación: Referencias fantasma > referencias débiles > referencias suaves > referencias fuertes

📦 Marco de colecciones

16. ¿Cuál es la estructura del marco de colecciones de Java?

Dominar el concepto general del marco de colecciones

  • Interfaz Collection:
  • List: Ordenado repetible, como ArrayList, LinkedList
  • Set: Desordenado no repetible, como HashSet, TreeSet
  • Queue: Cola, como LinkedList, PriorityQueue
  • Interfaz Map:
  • Mapeo de pares clave-valor: HashMap, TreeMap, ConcurrentHashMap
  • Jerarquía general: Iterable → Collection/Map → Clases de implementación específicas

17. ¿Cuál es la diferencia entre ArrayList y LinkedList?

Contrastar dos implementaciones de lista comunes

  • Estructura de datos: ArrayList basado en matriz, LinkedList basado en lista doblemente vinculada
  • Acceso aleatorio: ArrayList O(1), LinkedList O(n)
  • Inserción eliminación: ArrayList O(n), LinkedList O(1)
  • Ocupación de memoria: ArrayList continuo, LinkedList disperso (gastos de punteros)
  • Seguridad de hilos: Ambos no sincronizados, pueden usar Collections.synchronizedList() o CopyOnWriteArrayList
  • Selección: Usar ArrayList para consultas frecuentes, LinkedList para inserciones/eliminaciones frecuentes

18. ¿Cuál es el principio y rendimiento de HashMap?

Comprender profundamente el mecanismo de trabajo de HashMap

  • Estructura de datos: Matriz + lista vinculada + árbol rojo-negro (JDK 8+)
  • Principio de funcionamiento: hash(key) % table.length calcula índice de matriz, colisión se vincula o se arboli
  • Factor de carga: Por defecto 0.75, cuando capacidad usada ≥ capacidad × factor de carga se amplía
  • Mecanismo de ampliación: Capacidad se duplica, elementos se rehacen
  • Complejidad de tiempo: Promedio O(1), peor O(n) (muchas colisiones)
  • Seguridad de hilos: No sincronizado, multihilo usar ConcurrentHashMap o Collections.synchronizedMap()

19. ¿Cómo HashSet garantiza que no hay duplicados?

Comprender el mecanismo de deduplicación de Set

  • Implementación subyacente: Basado en HashMap, clave es el elemento, valor es Object fijo
  • Mecanismo de deduplicación: Primero comparar hashCode(), luego usar equals() para juzgar igualdad
  • Proceso de adición: Calcular hash → verificar existencia → no existe agregar → existe ignorar
  • Objeto personalizado: Debe sobrescribir equals() y hashCode(), garantizar consistencia
  • Rendimiento: Agregar, eliminar, buscar promedio O(1), depende de calidad de hash

20. ¿Qué son fail-fast y fail-safe?

Comprender el mecanismo de seguridad del iterador de colecciones

  • fail-fast:
  • Modificar la colección durante la iteración lanzará ConcurrentModificationException
  • Detectar a través de modCount y expectedModCount
  • Como ArrayList, HashMap (no thread-safe)
  • fail-safe:
  • La iteración se basa en una captura o copia de la colección, modificar la colección original no afecta la iteración
  • Como CopyOnWriteArrayList, ConcurrentHashMap
  • Sugerencia de uso: Usar remove() del iterador durante la iteración, o usar colecciones fail-safe

⚠️ Manejo de excepciones

21. ¿Cuál es la jerarquía de excepciones de Java?

Comprender la clasificación de excepciones de Java

  • Throwable (clase raíz):
  • Exception (excepción): Excepción recuperable
  • Error (error): Error a nivel de máquina virtual, no recuperable
  • Clasificación de Exception:
  • Excepción comprobada (Checked): Debe capturarse o declararse, como IOException
  • Excepción no comprobada (Unchecked): Puede no capturarse, como NullPointerException, IndexOutOfBoundsException
  • Excepciones comunes: NPE, ClassCastException, ArrayIndexOutOfBoundsException, etc.

22. ¿Cuál es el orden de ejecución de try-catch-finally?

Dominar el flujo de ejecución del manejo de excepciones

  • Caso normal: try → finally → retorno normal
  • Caso de excepción: try → excepción ocurre → catch → finally → propagación de excepción o retorno
  • Característica de finally: Se ejecuta definitivamente, incluso si return, throw, System.exit() en catch
  • Caso excepcional: return en finally sobrescribe el return de try/catch
  • Liberación de recursos: Recomendado usar try-with-resources, cierre automático de recursos
  • Mejor práctica: No cambiar el valor de retorno en finally, causará pérdida de excepción

23. ¿Cuál es la diferencia entre throws y throw?

Distinguir entre dos palabras clave de manejo de excepciones

  • throw:
  • Lanzar manualmente una instancia de excepción, debe usarse dentro de un método
  • Formato: throw new Exception("message")
  • throws:
  • Declarar en la firma del método las excepciones que pueden ser lanzadas
  • Formato: public void method() throws IOException
  • Forma de procesamiento: throw lanzado por throws, throws procesado por llamador
  • Aplicación: throw se usa para procesamiento de excepciones específicas, throws se usa para propagación de excepciones

24. ¿Cómo personalizar una excepción?

Crear clases de excepción específicas del proyecto

  • Relación de herencia: Heredar Exception (excepción comprobada) o RuntimeException (excepción no comprobada)
  • Partes necesarias:
  • Proporcionar constructor sin parámetros
  • Proporcionar constructor con parámetro message
  • Proporcionar constructor con parámetros message y cause
  • Ejemplo de código: public class CustomException extends Exception { ... }
  • Mejor práctica: Nombrar claramente, documentación clara, heredar de clase de excepción apropiada

25. ¿Cuáles son los beneficios de la sintaxis try-with-resources?

Comprender la gestión automática de recursos

  • Sintaxis: try (InputStream is = ...) { ... } cierra recursos automáticamente
  • Requisito: El recurso debe implementar la interfaz AutoCloseable
  • Ventajas:
  • Llamar automáticamente al método close(), sin necesidad de gestión manual
  • Procesar correctamente cuando las excepciones se suprimen
  • Código más conciso, evita fugas de recursos
  • Escenarios aplicables: File, Stream, Connection, Statement y otras clases de recursos

🔤 String, StringBuilder, StringBuffer

26. ¿Cuál es la inmutabilidad de String y sus razones?

Comprender las consideraciones profundas del diseño de String

  • Definición de inmutabilidad: Después de crear un objeto String, no se puede modificar, cualquier operación de modificación devuelve un nuevo objeto
  • Forma de implementación: El array value es modificado con final, sin método setter
  • Razones de inmutabilidad:
  • Optimización del grupo de buffer de strings, evita duplicación
  • Seguridad de hilos, sin necesidad de sincronización
  • Soportar caché hashCode, adecuado para clave de HashMap
  • Desventaja: Muchos objetos intermedios al modificar frecuentemente

27. ¿Cuál es la diferencia entre String, StringBuilder y StringBuffer?

Elegir la clase de operación de string adecuada

  • String: Inmutable, thread-safe, rendimiento pobre (modificación frecuente)
  • StringBuilder: Mutable, no thread-safe, rendimiento excelente (un solo hilo)
  • StringBuffer: Mutable, thread-safe (métodos sincronizados), rendimiento general (múltiples hilos)
  • Comparación de rendimiento: StringBuilder > StringBuffer > String
  • Recomendación de uso:
  • Concatenación de strings un solo hilo usar StringBuilder
  • Concatenación de strings múltiples hilos usar StringBuffer
  • No necesita modificación usar String

28. ¿Qué es el grupo de constantes de strings?

Comprender el mecanismo de caché de strings

  • Definición: JVM mantiene caché de strings, almacena strings literales
  • Ubicación: JDK 7+ en montículo, antes en área de métodos
  • Mecanismo de creación:
  • Literales como "abc" entran automáticamente al grupo
  • new String("abc") si "abc" no está en grupo se agrega
  • Método intern(): Agregar string al grupo o devolver referencia existente
  • Efecto de optimización: Ahorrar memoria, acelerar comparación de strings

29. ¿Cómo comparar igualdad de strings?

Dominar métodos de comparación de strings

  • Comparación ==: Compara si las referencias son iguales, no compara contenido
  • Comparación equals(): Compara si el contenido de strings es igual, recomendado usar
  • Comparación equalsIgnoreCase(): Comparar contenido ignorando mayúsculas/minúsculas
  • Comparación compareTo(): Comparación de orden lexicográfico, devuelve entero
  • Objects.equals(): Comparación segura manejando valores nulos
  • Mejor práctica: Usar equals() para comparar contenido de strings, evitar ==

30. ¿Cuáles son los problemas de rendimiento de concatenación de strings?

Optimizar el rendimiento de concatenación de strings

  • Problema: String s = "a" + "b" + "c" produce múltiples objetos intermedios y copias
  • Razón: String es inmutable, cada concatenación crea nuevo objeto
  • Impacto de rendimiento: Concatenación en bucle complejidad de tiempo O(n²)
  • Plan de optimización:
  • Directamente + fuera del bucle: compilador optimizará a StringBuilder
  • Usar explícitamente StringBuilder o StringBuffer
  • Usar herramientas String.join(), StringJoiner, etc.

🔄 Multihilo y concurrencia

31. ¿Qué es un hilo? ¿Cómo crear hilos?

Dominar conceptos básicos de hilos y métodos de creación

  • Definición de hilo: Flujo de ejecución independiente dentro de un proceso, compartir memoria pero tener pila independiente
  • Métodos de creación:
  • Heredar Thread: public class MyThread extends Thread { public void run() {} }
  • Implementar Runnable: public class MyRunnable implements Runnable { public void run() {} }
  • Implementar Callable: Soporte para valor de retorno y excepciones
  • Diferencia: Runnable recomendado, evita limitación de herencia única
  • Iniciar: Llamar thread.start(), no puede llamar directamente run()

32. ¿Cuál es el ciclo de vida y estado de los hilos?

Comprender varios cambios de estado de los hilos

  • NEW: Hilo creado pero no iniciado
  • RUNNABLE: Estado ejecutable (esperando ejecutarse o en ejecución)
  • BLOCKED: Estado bloqueado, esperando adquirir cerradura
  • WAITING: Estado de espera, esperando notificación de otro hilo
  • TIMED_WAITING: Esperando tiempo especificado
  • TERMINATED: Hilo terminado
  • Cambio de estado: NEW → RUNNABLE → BLOCKED/WAITING → TERMINATED

33. ¿Cómo funciona synchronized?

Comprender el mecanismo de cerradura incorporada de Java

  • Mecanismo de sincronización: Usar cerradura incorporada de objeto para implementar sincronización
  • Forma de uso:
  • Método sincronizado: public synchronized void method() {}
  • Bloque sincronizado: synchronized(obj) { ... }
  • Principio de funcionamiento:
  • Cada objeto tiene un monitor
  • Hilo adquiere cerradura para entrar en sección crítica, ejecución mutuamente excluyente
  • Código de bytes: monitorenter, monitorexit
  • Características: Reentrable, exclusiva, liberación automática

34. ¿Cuál es el papel de la palabra clave volatile?

Comprender visibilidad de memoria y prohibición de reordenamiento

  • Papel:
  • Visibilidad: Garantizar que las modificaciones sean visibles inmediatamente para otros hilos
  • Prohibir reordenamiento: Impedir optimización de reordenamiento del compilador y CPU
  • Implementación: Barrera de memoria, forzar leer/escribir desde memoria principal
  • Limitación: No puede garantizar atomicidad, no puede reemplazar synchronized
  • Escenario de aplicación: Bandera, doble verificación singleton, marcador de estado
  • Contraste con synchronized: volatile más ligero pero funcionalidad limitada

35. ¿Cuál es el papel de wait(), notify() y notifyAll()?

Dominar el mecanismo de comunicación entre hilos

  • wait():
  • Hilo actual libera cerradura entra en espera, hasta ser despertado
  • Debe llamarse dentro de bloque sincronizado
  • notify():
  • Despierta un hilo en espera (selección aleatoria)
  • No libera cerradura, libera después de que bloque sincronizado termina
  • notifyAll():
  • Despierta todos los hilos en espera
  • Patrón de uso: Patrón Productor-Consumidor, patrón Monitor

💡 Consejos de preparación para entrevista

Profundizar en fundamentos: No solo conocer conceptos, sino entender principios e implementación

Más práctica: Consolidar conocimiento a través de práctica de codificación, especialmente multihilo y concurrencia

Leer código fuente: Investigar código fuente de biblioteca Java (colecciones, concurrencia, etc.) para profundizar comprensión

Prestar atención a detalles: Dominar trampas comunes y mejores prácticas, como comparación de strings, modificación de colecciones, etc.

Explicar con ejemplos: En entrevista usar ejemplos específicos para explicar conceptos, mejorar expresión