¿Qué es Java?
Java es un lenguaje de programación orientado a objetos que se utiliza para desarrollar aplicaciones multiplataforma. Fue diseñado para ser robusto, seguro y de alto rendimiento.
Ejemplo:
public class HolaMundo {
public static void main(String[] args) {
System.out.println("¡Hola Mundo!");
}
}
¿Qué es una clase en Java?
Una clase en Java es una plantilla o molde a partir del cual se crean objetos. Define atributos (variables) y métodos (funciones) que los objetos creados a partir de la clase pueden usar.
Ejemplo:
class Coche {
String color;
void arrancar() {
System.out.println("El coche arranca");
}
}
¿Qué es la herencia en Java?
La herencia en Java es un mecanismo que permite que una clase herede atributos y métodos de otra clase, permitiendo la reutilización de código. La clase que hereda es llamada subclase y la clase de la cual hereda es la superclase.
Ejemplo:
class Vehiculo {
void mover() {
System.out.println("El vehículo se mueve");
}
}
class Coche extends Vehiculo {
}
¿Qué es una interfaz en Java?
Una interfaz en Java es un conjunto de métodos abstractos que una clase debe implementar si decide utilizar la interfaz. Las interfaces permiten definir contratos que las clases deben cumplir sin especificar cómo lo hacen.
Ejemplo:
interface Volable {
void volar();
}
class Pajaro implements Volable {
public void volar() {
System.out.println("El pájaro vuela");
}
}
¿Qué es un constructor en Java?
Un constructor en Java es un método especial que se ejecuta al crear una instancia (objeto) de una clase. Se utiliza para inicializar los atributos de la clase.
Ejemplo:
class Persona {
String nombre;
Persona(String nombre) {
this.nombre = nombre;
}
}
¿Qué significa 'JDK'?
JDK significa "Java Development Kit". Es un conjunto de herramientas que incluye el compilador, las bibliotecas y otras utilidades necesarias para desarrollar aplicaciones en Java.
¿Qué es el 'garbage collection' en Java?
El 'garbage collection' es un proceso automático en Java que se encarga de liberar memoria eliminando los objetos que ya no son utilizados por el programa, ayudando a evitar fugas de memoria.
¿Cuál de los siguientes no es un tipo de dato primitivo en Java?
"String" no es un tipo de dato primitivo en Java, sino una clase. Los tipos primitivos incluyen int, boolean, char, entre otros.
¿Qué es un paquete en Java?
Un paquete en Java es una forma de organizar las clases relacionadas en grupos. Facilita la organización y evita conflictos de nombres entre clases.
Ejemplo:
package com.ejemplo.mipaquete;
¿Qué hace el método 'main' en Java?
El método
main es el punto de entrada para la ejecución de cualquier aplicación Java. Es donde comienza la ejecución del programa.
Ejemplo:
public static void main(String[] args) {
System.out.println("Inicia el programa");
}
¿Qué es un 'try-catch' en Java?
Un 'try-catch' es una estructura de control que se utiliza para manejar excepciones en Java. Permite intentar ejecutar un bloque de código y, si ocurre una excepción, manejarla adecuadamente en el bloque 'catch'.
Ejemplo:
try {
int resultado = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Error: División por cero");
}
¿Qué es una excepción en Java?
Una excepción en Java es un error que puede ocurrir durante la ejecución del programa, y puede ser manejado mediante estructuras de control como 'try-catch'. Las excepciones permiten que el programa continúe su ejecución en lugar de cerrarse abruptamente.
Ejemplo:
throw new Exception("Ocurrió un error");
¿Qué significa 'OOP'?
OOP significa "Orientación a Objetos". Es un paradigma de programación que utiliza "objetos" y sus interacciones para diseñar aplicaciones y programas. Las características principales de OOP incluyen encapsulamiento, herencia y polimorfismo.
¿Qué es una variable estática?
Una variable estática es una variable que pertenece a la clase en lugar de a una instancia específica. Esto significa que su valor es compartido por todas las instancias de la clase.
Ejemplo:
class Contador {
static int conteo = 0;
}
¿Qué hace el operador 'instanceof' en Java?
El operador 'instanceof' se utiliza para verificar si un objeto es una instancia de una clase específica o de una subclase.
Ejemplo:
if (objeto instanceof Coche) {
System.out.println("Es un coche");
}
¿Qué es el 'polimorfismo' en Java?
El polimorfismo en Java es la capacidad de un objeto de tomar muchas formas. Permite que una misma operación se realice de diferentes maneras dependiendo del objeto que la invoca.
Ejemplo:
class Animal {
void hacerSonido() {
System.out.println("Sonido genérico");
}
}
class Perro extends Animal {
void hacerSonido() {
System.out.println("Guau");
}
}
¿Qué es un 'ArrayList' en Java?
Un 'ArrayList' en Java es una colección que puede cambiar de tamaño dinámicamente. Permite almacenar elementos de manera ordenada y proporciona métodos para manipular la lista, como agregar, eliminar y acceder a elementos.
Ejemplo:
ArrayList<String> lista = new ArrayList<>();
lista.add("Elemento 1");
¿Qué es un 'HashMap' en Java?
Un 'HashMap' en Java es una estructura de datos que almacena pares clave-valor. Permite acceder a los elementos de manera rápida utilizando la clave asociada.
Ejemplo:
HashMap<String, Integer> mapa = new HashMap<>();
mapa.put("Uno", 1);
¿Qué es un 'Thread' en Java?
Un 'Thread' en Java es una unidad de ejecución en un programa. Permite la ejecución concurrente de dos o más partes de un programa, lo que mejora la eficiencia y el rendimiento.
Ejemplo:
class MiHilo extends Thread {
public void run() {
System.out.println("Hilo en ejecución");
}
}
¿Qué hace el método 'finalize' en Java?
El método 'finalize' se invoca cuando un objeto es recolectado por el 'garbage collector'. Puede ser utilizado para liberar recursos o realizar limpieza antes de que el objeto sea destruido.
Ejemplo:
protected void finalize() throws Throwable {
System.out.println("Objeto eliminado");
}
¿Qué es 'JavaFX'?
JavaFX es un conjunto de bibliotecas en Java que permite crear interfaces gráficas de usuario (GUI) con una apariencia moderna. Es utilizado para desarrollar aplicaciones de escritorio y móviles.
¿Qué es 'JUnit'?
JUnit es un marco de trabajo para realizar pruebas unitarias en Java. Permite verificar que las partes individuales del código funcionen correctamente.
Ejemplo:
@Test
public void testSuma() {
assertEquals(5, 2 + 3);
}
¿Qué es 'Maven'?
Maven es una herramienta de automatización de construcción y gestión de proyectos en Java. Se utiliza para gestionar las dependencias, compilar el código y empaquetar aplicaciones.
¿Qué es Spring Boot y cuáles son sus ventajas?
Spring Boot es un marco de trabajo basado en el framework Spring que simplifica el desarrollo de
aplicaciones Java al proporcionar configuraciones automáticas y convenciones sobre configuraciones. Sus ventajas
incluyen una configuración mínima, un inicio rápido de aplicaciones, integración con otros proyectos de Spring, y
una amplia variedad de funcionalidades integradas, como soporte para bases de datos, seguridad y gestión de
dependencias.
¿Cómo se crea un proyecto en Spring Boot?
Se puede crear un proyecto en Spring Boot utilizando el Spring Initializr, una herramienta en
línea que permite seleccionar dependencias, versiones de Java y otras configuraciones iniciales. Alternativamente,
se puede usar un IDE como IntelliJ IDEA o Spring Tool Suite que tenga integración con Spring Boot para crear un
proyecto desde cero.
¿Qué son las anotaciones @RestController y @RequestMapping en Spring Boot?
La anotación @RestController es una combinación de @Controller y
@ResponseBody, que indica que la clase es un controlador donde los métodos devuelven datos en lugar
de vistas. La anotación @RequestMapping se utiliza para mapear solicitudes HTTP a métodos específicos
en un controlador. Permite definir la URL, el método HTTP y otros parámetros.
¿Cómo se maneja la inyección de dependencias en Spring Boot?
La inyección de dependencias en Spring Boot se gestiona a través de anotaciones como
@Autowired, que permite que Spring resuelva y proporcione automáticamente las dependencias requeridas
por los componentes. Esto se puede aplicar a clases de servicio, controladores y repositorios.
¿Qué es un Bean en Spring y cómo se define?
Un Bean en Spring es un objeto que forma parte del contexto de la aplicación y es gestionado por
el contenedor de Spring. Se puede definir un Bean utilizando la anotación @Component,
@Service, @Repository, o mediante métodos anotados con @Bean dentro de una
clase marcada con @Configuration.
¿Qué es la configuración basada en Java en Spring Boot?
La configuración basada en Java en Spring Boot permite definir Beans y configuraciones
utilizando clases Java en lugar de archivos XML. Esto proporciona una forma más clara y fácil de entender para
configurar aplicaciones y utilizar la inyección de dependencias mediante anotaciones.
¿Cómo se manejan las excepciones en Spring Boot?
En Spring Boot, las excepciones se pueden manejar utilizando @ControllerAdvice, que
permite definir un controlador global para manejar excepciones de manera centralizada. También se pueden usar
@ExceptionHandler para manejar excepciones específicas en controladores individuales.
¿Cómo se configuran las propiedades de la aplicación en Spring Boot?
Las propiedades de la aplicación en Spring Boot se configuran en el archivo
application.properties o application.yml. Estas propiedades pueden incluir
configuraciones como la conexión a la base de datos, el puerto del servidor, y otras configuraciones
personalizadas. Spring Boot carga automáticamente estas propiedades al iniciar la aplicación.
¿Qué es Spring Data JPA y cómo se utiliza en Spring Boot?
Spring Data JPA es un proyecto de Spring que facilita la interacción con bases de datos
utilizando la especificación JPA (Java Persistence API). En Spring Boot, se puede utilizar simplemente añadiendo
la dependencia de spring-boot-starter-data-jpa en el archivo pom.xml. Se pueden crear
interfaces de repositorio que extienden JpaRepository para realizar operaciones CRUD sin necesidad de
implementar el código de acceso a datos.
¿Cuál es la última versión de Java actualmente?
La última versión de Java es Java 21, lanzada en septiembre de 2023. Esta versión incluye nuevas
características como patrones de coincidencia, mejoras en el rendimiento y soporte para la programación funcional,
lo que la convierte en una opción más eficiente y fácil de usar para desarrolladores.
¿Cuál es la última versión de JDK?
La última versión del Java Development Kit (JDK) es la versión 21. Este kit incluye herramientas
necesarias para desarrollar aplicaciones en Java, como el compilador y el entorno de ejecución. Mantenerse
actualizado con la última versión es crucial para aprovechar las nuevas funcionalidades y mejoras de rendimiento.
¿Qué diferencia hay entre el JDK y el JRE?
El JDK (Java Development Kit) incluye herramientas para desarrollar aplicaciones Java, mientras
que el JRE (Java Runtime Environment) proporciona las bibliotecas y recursos necesarios para ejecutar aplicaciones
Java. En resumen, si deseas programar en Java, necesitas el JDK, pero si solo deseas ejecutar aplicaciones, el JRE
es suficiente.
¿Qué es la programación funcional e imperativa?
La programación funcional es un paradigma que trata el cálculo como la evaluación de funciones y
evita el uso de estados y datos mutables. Por otro lado, la programación imperativa se basa en comandos que
cambian el estado del programa, enfocándose en cómo se debe realizar una tarea. Ambos paradigmas ofrecen
diferentes enfoques para resolver problemas de programación.
¿A partir de qué versión de Java se implementó la programación funcional?
La programación funcional fue implementada en Java 8, lanzada en marzo de 2014. Esta versión
introdujo características como expresiones lambda y Streams, que facilitan la programación funcional y permiten a
los desarrolladores escribir código más limpio y conciso.
Características de la POO. Ejemplos de aplicación de cada uno.
La Programación Orientada a Objetos (POO) tiene varias características clave:
- Encapsulamiento: Agrupamiento de datos y métodos que operan sobre ellos, limitando el
acceso externo. Ejemplo: una clase `Coche` con atributos privados y métodos públicos para acceder y modificar
esos atributos.
- Herencia: Permite crear nuevas clases basadas en clases existentes, reutilizando código.
Ejemplo: una clase `Vehiculo` que es extendida por `Coche` y `Motocicleta`.
- Polimorfismo: Permite que diferentes clases puedan ser tratadas como instancias de la misma
clase a través de una interfaz común. Ejemplo: un método `dibujar` que puede ser implementado de diferentes
maneras en distintas clases que implementan una interfaz `Dibujable`.
Diferencias entre una clase abstracta y una interfaz.
Una clase abstracta puede contener métodos concretos (con implementación) y abstractos (sin
implementación), mientras que una interfaz solo puede contener métodos abstractos y constantes. En una clase
abstracta, puedes definir un comportamiento base, mientras que una interfaz es un contrato que las clases
implementadoras deben cumplir. Esto permite a las interfaces ser más flexibles, ya que una clase puede implementar
múltiples interfaces, mientras que solo puede extender una clase abstracta.
Diferencia entre HashMap y LinkedList. Ejemplos de implementación.
`HashMap` es una implementación de mapa que almacena pares clave-valor, permite acceder a los
valores rápidamente mediante claves, pero no mantiene el orden de inserción. Ejemplo:
HashMap<String, Integer> mapa = new HashMap<>();
mapa.put("uno", 1);
mapa.put("dos", 2);
`LinkedList` es una implementación de lista que permite inserciones y eliminaciones rápidas, pero el acceso a los
elementos es más lento en comparación con los arrays. Ejemplo:
LinkedList<String> lista = new LinkedList<>();
lista.add("uno");
lista.add("dos");
¿Cómo hacer un deploy?
El despliegue de una aplicación implica varios pasos, como preparar el entorno de producción,
compilar el código, realizar pruebas, y luego transferir los archivos al servidor. Puedes usar herramientas de
integración continua como Jenkins o GitHub Actions para automatizar este proceso. Es importante asegurarte de que
el entorno de producción tenga las mismas configuraciones que el entorno de desarrollo para evitar problemas al
ejecutar la aplicación.
¿Cómo hacer pruebas de backend si no tienes un frontend?
Puedes realizar pruebas de backend utilizando herramientas como Postman o cURL para hacer
solicitudes HTTP a las APIs. También puedes escribir pruebas unitarias y de integración utilizando frameworks como
JUnit y Mockito, que permiten simular el comportamiento de las dependencias y verificar que el código funcione
correctamente sin necesidad de una interfaz gráfica.
Diferencias entre Spring y Spring Boot.
Spring es un framework para desarrollar aplicaciones en Java que proporciona características
como inyección de dependencias y programación orientada a aspectos. Spring Boot, por otro lado, es una extensión
de Spring que facilita la creación de aplicaciones de producción, proporcionando configuración automática y un
enfoque de "convención sobre configuración". Esto significa que Spring Boot permite desarrollar aplicaciones más
rápidamente, eliminando la necesidad de configurar manualmente la mayoría de las características.
¿Utilizaste control de versiones? ¿Cómo volver un commit atrás?
Sí, utilicé control de versiones, principalmente Git. Para volver a un commit anterior, puedes
usar el comando `git checkout <commit_id>` para ver el estado del repositorio en ese commit. Si deseas
revertir el último commit, puedes usar `git revert HEAD` o `git reset --hard <commit_id>` para deshacer
cambios, aunque este último eliminará cambios posteriores en tu historial.
¿Qué patrones de diseño conoces?
Conozco varios patrones de diseño, entre ellos:
- Singleton: Garantiza que una clase tenga una única instancia y proporciona un punto de
acceso global a ella.
- Factory: Proporciona una interfaz para crear objetos en una clase base, permitiendo a las
subclases modificar el tipo de objetos que se crearán.
- Observer: Define una dependencia de uno a muchos entre objetos, de manera que cuando un
objeto cambia de estado, todos sus dependientes son notificados.
Diferencias entre un árbol binario y un árbol AVL.
Un árbol binario es una estructura de datos donde cada nodo tiene hasta dos hijos. Sin embargo,
un árbol AVL es un tipo de árbol binario auto-balanceado, donde la diferencia de altura entre los subárboles
izquierdo y derecho de cualquier nodo no puede ser mayor que uno. Esto permite que un árbol AVL mantenga un tiempo
de búsqueda, inserción y eliminación en O(log n), mientras que en un árbol binario, estos tiempos pueden ser O(n)
en el peor caso si el árbol no está balanceado.
Preguntas y Respuestas sobre Programación Funcional
¿Qué es la programación funcional?
La programación funcional es un paradigma de programación en el que las funciones son tratadas como ciudadanos de primera clase. Esto significa que se pueden pasar como argumentos, retornar desde otras funciones y almacenarse en variables. Se enfoca en el uso de funciones puras, la inmutabilidad y la evitación de efectos secundarios.
Ejemplo en Java:
Function<Integer, Integer> cuadrado = x -> x * x;
System.out.println(cuadrado.apply(5)); // Salida: 25
¿Qué es una función pura?
Una función pura es aquella que siempre devuelve el mismo resultado cuando se le da la misma entrada y no tiene efectos secundarios. Esto facilita la razonabilidad y pruebas de los programas.
Ejemplo:
int suma(int a, int b) {
return a + b; // Esta es una función pura
}
¿Qué es la inmutabilidad en programación funcional?
La inmutabilidad es el principio según el cual los datos no pueden ser modificados una vez creados. En lugar de modificar los valores existentes, se crean nuevos valores, lo que previene efectos secundarios y errores impredecibles.
Ejemplo en Java:
List<Integer> lista = Arrays.asList(1, 2, 3);
List<Integer> nuevaLista = lista.stream().map(x -> x * 2).collect(Collectors.toList());
¿Qué es una expresión lambda?
Una expresión lambda es una función anónima que puede ser tratada como cualquier otro objeto. Se utilizan principalmente para simplificar el código al representar funciones de una manera concisa y legible.
Ejemplo en Java:
List<String> nombres = Arrays.asList("Ana", "Juan", "Pedro");
nombres.forEach(nombre -> System.out.println(nombre));
¿Cuáles son los tipos de formato de una expresión lambda en Java?
Existen diferentes formas de escribir una expresión lambda en Java, dependiendo de la cantidad de parámetros y la longitud del cuerpo de la función:
- Lambdas sin parámetros: Se utilizan cuando no se necesita ningún argumento.
Ejemplo:
() -> System.out.println("¡Hola Mundo!");
- Lambdas con un parámetro: Si se tiene un solo parámetro, no es necesario rodearlo con paréntesis.
Ejemplo:
x -> x * x;
- Lambdas con varios parámetros: Se utilizan paréntesis para agrupar los parámetros.
Ejemplo:
(x, y) -> x + y;
- Lambdas con varias líneas de código: Se utiliza un bloque de código rodeado de llaves si la función tiene varias líneas.
Ejemplo:
(x, y) -> {
int resultado = x + y;
System.out.println("Resultado: " + resultado);
return resultado;
};
Principales interfaces funcionales en Java
A continuación se presentan algunas de las interfaces funcionales más comunes en Java:
- Consumer: Representa una operación que acepta un solo argumento y no devuelve resultado. Se usa comúnmente para realizar acciones sobre los elementos de una colección.
Ejemplo:
Consumer imprimir = s -> System.out.println(s);
- Supplier: Representa una función que no acepta argumentos y devuelve un resultado. Es útil para generar valores.
Ejemplo:
Supplier generarAleatorio = () -> Math.random();
- Function: Representa una función que acepta un argumento y devuelve un resultado. Permite transformar datos.
Ejemplo:
Function longitud = s -> s.length();
- BiFunction: Similar a `Function`, pero acepta dos argumentos y devuelve un resultado.
Ejemplo:
BiFunction suma = (a, b) -> a + b;
- Predicate: Representa una función que acepta un argumento y devuelve un valor booleano. Se utiliza comúnmente para evaluar condiciones.
Ejemplo:
Predicate esPar = n -> n % 2 == 0;
¿Qué es la composición de funciones?
La composición de funciones es el proceso de combinar dos o más funciones para producir una nueva función. Es fundamental en la programación funcional ya que permite construir funciones complejas a partir de funciones simples.
Ejemplo en Java:
Function<Integer, Integer> doble = x -> x * 2;
Function<Integer, Integer> cuadrado = x -> x * x;
Function<Integer, Integer> dobleYCuadrado = doble.andThen(cuadrado);
System.out.println(dobleYCuadrado.apply(3)); // Salida: 36