📚 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