├── 1. Internet ├── 1.Cómo funciona Internet.md ├── 2.Qué es HTTP.md ├── 3.La diferencia entre HTTP y HTTPS.md ├── 4.Métodos HTTP (Usando Java).md ├── 5.Qué es un nombre de dominio.md ├── 6.Qué es el Hosting.md └── 7.Cómo funcionan los navegadores.md ├── 2.Java ├── 1.Que es java.md ├── 10.Fechas y horas.md ├── 2.Tipos de datos y variables en java.md ├── 3.Condicionales simples y multiples.md ├── 4.Condicional Switch.md ├── 5.Bucle While.md ├── 6.Bucles For.md ├── 7.Vectores (Arrays).md ├── 8.Matrices.md └── 9.Funciones.md ├── 3.Java POO ├── 11.POO Programación Orientada a Objetos.md ├── 12.Que son las clases y como crearla.md ├── 13.Metodos y como crearlos.md ├── 14.Métodos Constructores y Objetos En Java.md ├── 15.Getters y Setters en java.md ├── 16.Herencia en Java.md ├── 17.Polimorfismo en java.md ├── 18.Encapsulamiento en Java.md ├── 19.Clases Abstractas.md ├── 20.Interfaces en Java.md ├── 21.Collections en Java.md ├── 22.ArrayList en Java.md ├── 23.LinkedList en java.md ├── 24.Diferencias entre ArrayLists y LinkedLists.md ├── 25.Stacks en java.md ├── 26.Maps en java.md ├── 27.Excepciones en Java.md ├── 28.Relaciones entre Clases en Java.md ├── 29.Conversiones entre Tipos de Datos.md ├── 30.ENUMS o enumeraciones en java.md ├── 31.Generics o génericos en java.md ├── 32.JPA (Java Persistence Api).md ├── 33.Annotations en JPA.md ├── 34.JPA Controllers.md ├── 35.CRUD en JPA CREATE.md ├── 36.CRUD en JPA Delete y Edit.md ├── 37.CRUD con JPA Find y FindEntities.md ├── 38.CRUD con JPA Relacion OneToOne.md └── 39.CRUD con JPA Relacion OneToMany.md ├── 4.Spring Boot ├── 40.Librerías vs Frameworks.md ├── 41.Spring Framework.md ├── 42.Spring Boot.md ├── 43.Spring Initializr.md ├── 44.Patrón MVC.md ├── 45.ApisRest.md ├── 46.Primer API con Spring Boot.md ├── 47.@GetMapping y @PathVariable.md ├── 48.@RequestParam .md ├── 49.Que es JSON.md ├── 50.@PostMapping + @RequestBody.md ├── 51.@ResponseBody + ResponseEntity.md ├── 52.Patrón DTO (Data Transfer Object).md ├── 53.Arquitectura multicapa.md ├── 54.@Repository y @Service.md ├── 55.Inversión de Control .md ├── 56.@Autowired.md ├── 57.@Data.md ├── 58.Hibernate.md └── 59.Relaciones @OneToOne, @OneToMany y @ManyToMany.md ├── 5.Spring Security ├── 60.Autenticación vs Autorización.md ├── 61.Stateful vs Stateless.md └── 62. Roles y Permisos.md ├── 6.Teoría └── Patrones vs Arquitecturas .md └── README.md /1. Internet/1.Cómo funciona Internet.md: -------------------------------------------------------------------------------- 1 | # ¿Cómo funciona Internet? 2 | 3 | #### Introducción 4 | 5 | Internet es una red global de computadoras interconectadas que permite a los usuarios compartir información y comunicarse entre sí de manera instantánea. Este vasto sistema interconectado de redes es complejo y multifacético, pero se puede descomponer en varios componentes clave para entender su funcionamiento. 6 | 7 | #### Historia y Evolución 8 | 9 | Internet se originó en la década de 1960 como ARPANET, un proyecto del Departamento de Defensa de los Estados Unidos para desarrollar una red de comunicaciones resistente. Con el tiempo, ARPANET se expandió y evolucionó, incorporando diversas tecnologías y protocolos que dieron lugar a lo que hoy conocemos como Internet. 10 | 11 | #### Componentes Clave 12 | 13 | 1. **Infraestructura Física:** 14 | - **Servidores y Centros de Datos:** Computadoras potentes que almacenan y distribuyen datos. 15 | - **Cables de Fibra Óptica:** Transportan datos a gran velocidad a través de largas distancias. 16 | - **Enrutadores y Switches:** Dispositivos que dirigen el tráfico de datos hacia sus destinos. 17 | 18 | 2. **Proveedores de Servicios de Internet (ISP):** 19 | - Los ISP son empresas que proporcionan acceso a Internet a los usuarios finales. Funcionan como intermediarios entre los usuarios y la infraestructura global de Internet. 20 | 21 | 3. **Direcciones IP y DNS:** 22 | - **Direcciones IP:** Cada dispositivo conectado a Internet tiene una dirección IP única que lo identifica, similar a una dirección postal. 23 | - **Sistema de Nombres de Dominio (DNS):** Traduce nombres de dominio fáciles de recordar (como www.google.com) en direcciones IP. 24 | 25 | 4. **Protocolos de Comunicación:** 26 | - **TCP/IP (Transmission Control Protocol/Internet Protocol):** La columna vertebral de Internet, responsable de descomponer datos en paquetes, transmitirlos y asegurarse de que lleguen a su destino. 27 | - **HTTP/HTTPS (Hypertext Transfer Protocol/Secure):** Protocolos utilizados para la transferencia de páginas web. 28 | 29 | 5. **Navegadores Web y Aplicaciones:** 30 | - **Navegadores Web:** Programas como Chrome, Firefox y Safari que permiten a los usuarios acceder y navegar por sitios web. 31 | - **Aplicaciones:** Programas y servicios que utilizan Internet para funcionar, como correos electrónicos, redes sociales y servicios de streaming. 32 | 33 | #### Funcionamiento de la Comunicación en Internet 34 | 35 | 1. **Solicitud del Usuario:** 36 | - Cuando un usuario ingresa una URL en su navegador, este envía una solicitud a un servidor DNS para obtener la dirección IP correspondiente. 37 | 38 | 2. **Resolución DNS:** 39 | - El servidor DNS traduce el nombre de dominio en una dirección IP y la devuelve al navegador. 40 | 41 | 3. **Transmisión de Datos:** 42 | - El navegador envía una solicitud HTTP/HTTPS al servidor web asociado con la dirección IP. 43 | 44 | 4. **Respuesta del Servidor:** 45 | - El servidor web procesa la solicitud y envía de vuelta los datos solicitados (como una página web) al navegador. 46 | 47 | 5. **Renderización de la Página Web:** 48 | - El navegador recibe los datos y los interpreta, mostrando la página web al usuario. 49 | 50 | #### Seguridad en Internet 51 | 52 | - **Cifrado:** HTTPS utiliza cifrado para proteger la transmisión de datos entre el navegador y el servidor. 53 | - **Firewalls y Antivirus:** Protegen los dispositivos y redes de accesos no autorizados y malware. 54 | - **Autenticación y Autorización:** Aseguran que solo usuarios legítimos tengan acceso a ciertos recursos. 55 | 56 | #### Internet de las Cosas (IoT) 57 | 58 | - **Dispositivos Conectados:** Desde teléfonos inteligentes hasta refrigeradores, muchos dispositivos ahora pueden conectarse a Internet, creando un ecosistema interconectado. 59 | 60 | #### Impacto Social y Económico 61 | 62 | - **Comunicación Global:** Permite la comunicación instantánea entre personas de todo el mundo. 63 | - **Acceso a Información:** Facilita el acceso a vastos recursos de información y conocimiento. 64 | - **Comercio Electrónico:** Ha transformado la forma en que se realizan negocios, permitiendo el comercio electrónico y la globalización de mercados. 65 | 66 | **Ejemplo para Simplificar:** 67 | Imagina que Internet es como un sistema postal global. Los servidores son las oficinas postales que almacenan y envían paquetes (datos). Los cables de fibra óptica son las carreteras y rutas aéreas que transportan esos paquetes. Las direcciones IP son como las direcciones de casas y negocios, y el DNS es el servicio de directorio que traduce nombres fáciles de recordar (nombres de dominio) en direcciones físicas. Los protocolos como TCP/IP aseguran que los paquetes lleguen a su destino correctamente, y los navegadores web son los carteros que entregan los paquetes directamente a tu puerta (tu pantalla). 68 | 69 | Este sistema permite que cuando ingresas una dirección web en tu navegador, el "cartero" (navegador) sepa exactamente a dónde ir, encuentre el "paquete" (datos) correcto y te lo entregue de manera rápida y segura, permitiéndote acceder a la información o servicio que deseas. 70 | 71 | ### Conclusión 72 | 73 | En resumen, Internet funciona gracias a una compleja red de infraestructura física, proveedores de servicios, direcciones IP y sistemas DNS, protocolos de comunicación, y aplicaciones. A través de estos componentes, los datos pueden transmitirse de un punto a otro de manera eficiente y segura. 74 | 75 | ![GIF ilustrativo de como funciona el internet](https://media1.tenor.com/m/t3YlogZLsjoAAAAd/embedded-security-for-internet-of-things.jpg) -------------------------------------------------------------------------------- /1. Internet/2.Qué es HTTP.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es HTTP? 2 | 3 | **HTTP** (HyperText Transfer Protocol) es el lenguaje que utilizan los dispositivos conectados a internet para "conversar" entre sí. Imagina que es el idioma universal que permite que tu navegador web pueda solicitar y recibir información de un servidor remoto, como el de tu sitio web favorito. 4 | 5 | ### ¿Cómo funciona? 6 | 1. **Solicitud:** Cuando escribes una dirección web en tu navegador y presionas Enter, estás enviando una **solicitud HTTP** al servidor donde se encuentra ese sitio web. Esta solicitud le dice al servidor: "Por favor, envíame la página que corresponde a esta dirección". 7 | 2. **Respuesta:** El servidor recibe la solicitud, busca la página solicitada y la envía de vuelta a tu navegador en forma de una **respuesta HTTP**. Esta respuesta contiene el código HTML de la página, las imágenes, los videos y cualquier otro recurso necesario para que puedas verla en tu pantalla. 8 | 9 | ### Características clave de HTTP: 10 | * **Sin estado:** HTTP no "recuerda" las conexiones anteriores. Cada solicitud es independiente de las demás. Esto significa que si quieres mantener una sesión activa (como al iniciar sesión en un sitio web), se necesitan mecanismos adicionales como cookies o tokens de sesión. 11 | * **Cliente-servidor:** HTTP sigue un modelo de comunicación cliente-servidor. El cliente (tu navegador) inicia la comunicación y el servidor responde. 12 | * **Métodos HTTP:** Existen diferentes métodos HTTP para realizar distintas acciones, como: 13 | * **GET:** Se utiliza para solicitar un recurso (por ejemplo, una página web). 14 | * **POST:** Se utiliza para enviar datos a un servidor (por ejemplo, al enviar un formulario). 15 | * **PUT:** Se utiliza para actualizar un recurso existente. 16 | * **DELETE:** Se utiliza para eliminar un recurso. 17 | * Y muchos otros. 18 | 19 | ### ¿Por qué es importante HTTP? 20 | * **Base de la web:** HTTP es el protocolo fundamental que permite la comunicación entre los navegadores y los servidores web, haciendo posible la World Wide Web. 21 | * **Versátil:** HTTP se utiliza no solo para páginas web, sino también para muchas otras aplicaciones y servicios en línea. 22 | * **Evoluciona constantemente:** HTTP ha evolucionado a lo largo de los años, con nuevas versiones que introducen mejoras y características adicionales. 23 | 24 | ### Ejemplo práctico 25 | Cuando escribes "[https://www.google.com](https://www.google.com)" en tu navegador y presionas Enter, esto es lo que sucede: 26 | 1. Tu navegador envía una solicitud HTTP GET al servidor de Google solicitando la página principal. 27 | 2. El servidor de Google recibe la solicitud, busca la página principal y envía una respuesta HTTP con el código HTML de esa página. 28 | 3. Tu navegador recibe la respuesta, analiza el código HTML y muestra la página en tu pantalla. 29 | 30 | **Conclusión:** 31 | 32 | HTTP es el lenguaje básico que permite que la World Wide Web funcione. Es como el idioma que utilizan los computadores para comunicarse y compartir información a través de internet. Cada vez que visitas un sitio web, estás utilizando HTTP para solicitar y recibir datos. Aunque puede parecer complejo, la idea central es simple: un cliente (tu navegador) le pide algo a un servidor, y el servidor se lo proporciona. 33 | 34 | **En resumen:** HTTP es el protocolo que hace posible la experiencia de navegar por internet tal como la conocemos hoy en día. 35 | 36 | **¿Te gustaría profundizar más?** 37 | 38 | [La diferencia entre HTTP y HTTPS](./3.La%20diferencia%20entre%20HTTP%20y%20HTTPS.md) 39 | 40 | [Métodos HTTP (Usando Java)](./4.Métodos%20HTTP%20(Usando%20Java).md) -------------------------------------------------------------------------------- /1. Internet/3.La diferencia entre HTTP y HTTPS.md: -------------------------------------------------------------------------------- 1 | # La diferencia entre HTTP y HTTPS 2 | 3 | **HTTP** (HyperText Transfer Protocol) es el protocolo fundamental que permite la comunicación entre tu navegador y los servidores web. Es como el lenguaje básico que utilizan los dispositivos para "hablar" en internet. 4 | 5 | **HTTPS** (HyperText Transfer Protocol Secure) es una versión segura de HTTP. La principal diferencia radica en la **encriptación** de los datos. 6 | 7 | **¿Qué significa esto?** 8 | 9 | * **HTTP:** Los datos que se transmiten entre tu navegador y el servidor viajan en texto plano, como una postal sin sobre. Cualquiera podría interceptar esa postal y leer su contenido. 10 | * **HTTPS:** Los datos se cifran antes de enviarse, como si estuvieran dentro de un sobre cerrado con llave. Solo el destinatario (el servidor) y el remitente (tu navegador) tienen la llave para descifrarlos. 11 | 12 | **En resumen:** 13 | 14 | | Característica | HTTP | HTTPS | 15 | |---|---|---| 16 | | Seguridad | No seguro | Seguro (cifrado) | 17 | | Uso de certificados | No | Sí (SSL/TLS) | 18 | | Protección de datos | Vulnerable a interceptación | Protegido contra interceptación | 19 | | Indicador en el navegador | Normalmente http:// | Siempre https:// | 20 | 21 | **¿Por qué es importante HTTPS?** 22 | 23 | * **Protección de datos sensibles:** Cuando ingresas información personal en un sitio web (contraseñas, números de tarjetas de crédito), HTTPS garantiza que esa información esté protegida. 24 | * **Confianza del usuario:** Los navegadores suelen mostrar un candado o una barra de dirección verde para indicar que una conexión es segura. Esto aumenta la confianza de los usuarios. 25 | * **SEO:** Google favorece los sitios web que utilizan HTTPS, lo que puede mejorar su posicionamiento en los resultados de búsqueda. 26 | 27 | **En conclusión,** aunque ambos protocolos permiten la transmisión de datos en internet, HTTPS es la opción más segura y recomendada, especialmente para sitios web que manejan información confidencial. Si ves un candado en la barra de direcciones de tu navegador, significa que estás navegando en una conexión segura a través de HTTPS. -------------------------------------------------------------------------------- /1. Internet/4.Métodos HTTP (Usando Java).md: -------------------------------------------------------------------------------- 1 | # Métodos HTTP (Usando Java) 2 | 3 | **En Java con Spring Boot utilizamos los métodos HTTP (GET, POST, PUT, DELETE, etc.) al crear una API REST, pero de una manera más abstracta y declarativa.** 4 | 5 | **¿Cómo funciona?** 6 | 7 | * **Anotaciones:** Spring Boot utiliza anotaciones para mapear los métodos de tus controladores a los métodos HTTP correspondientes. Por ejemplo: 8 | * `@GetMapping`: Mapea un método a una solicitud HTTP GET. 9 | * `@PostMapping`: Mapea un método a una solicitud HTTP POST. 10 | * `@PutMapping`: Mapea un método a una solicitud HTTP PUT. 11 | * `@DeleteMapping`: Mapea un método a una solicitud HTTP DELETE. 12 | 13 | * **Controladores:** Los controladores son las clases que exponen los endpoints de tu API. Cada método dentro de un controlador representa un endpoint específico. 14 | 15 | **Ejemplo:** 16 | 17 | ```java 18 | @RestController 19 | @RequestMapping("/usuarios") 20 | public class UsuarioController { 21 | 22 | @GetMapping("/{id}") 23 | public Usuario obtenerUsuario(@PathVariable Long id) { 24 | // Lógica para obtener el usuario por ID 25 | } 26 | 27 | @PostMapping 28 | public Usuario crearUsuario(@RequestBody Usuario usuario) { 29 | // Lógica para crear un nuevo usuario 30 | } 31 | 32 | @PutMapping("/{id}") 33 | public Usuario actualizarUsuario(@PathVariable Long id, @RequestBody Usuario usuario) { 34 | // Lógica para actualizar un usuario existente 35 | } 36 | 37 | @DeleteMapping("/{id}") 38 | public void eliminarUsuario(@PathVariable Long id) { 39 | // Lógica para eliminar un usuario 40 | } 41 | } 42 | ``` 43 | 44 | En este ejemplo: 45 | 46 | * `@RestController`: Indica que esta clase es un controlador REST. 47 | * `@RequestMapping("/usuarios")`: Define la ruta base para todos los endpoints de este controlador. 48 | * `@GetMapping("/{id}")`: Mapea el método `obtenerUsuario` a una solicitud GET en la URL `/usuarios/{id}`. 49 | * `@PathVariable Long id`: Indica que el valor de `{id}` en la URL se asignará al parámetro `id` del método. 50 | 51 | **¿Por qué usar anotaciones en lugar de llamar directamente a los métodos HTTP?** 52 | 53 | * **Simplicidad:** Hace que el código sea más legible y fácil de entender. 54 | * **Conveniencia:** Spring se encarga de gran parte de la configuración y mapeo automáticamente. 55 | * **Flexibilidad:** Puedes personalizar el comportamiento utilizando interceptores y filtros. 56 | 57 | **En resumen,** aunque no escribes explícitamente `HttpGet`, `HttpPost`, etc., estás utilizando los métodos HTTP al anotar tus controladores. Spring se encarga de traducir estas anotaciones en las solicitudes HTTP correspondientes. -------------------------------------------------------------------------------- /1. Internet/5.Qué es un nombre de dominio.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es un nombre de dominio? 2 | 3 | Imagina que internet es una ciudad gigante y cada sitio web es una casa particular. Para encontrar una casa en específico, necesitas una dirección, ¿cierto? Pues bien, el nombre de dominio es como la dirección de una casa en internet. Es un nombre fácil de recordar que se asigna a una dirección numérica (IP) que las computadoras utilizan para comunicarse entre sí. Por ejemplo, en lugar de tener que recordar una larga secuencia de números como 192.168.1.1, puedes simplemente escribir "google.com" en tu navegador. 4 | 5 | **¿Cuál es la diferencia entre un nombre de dominio y una URL?** 6 | 7 | Si el nombre de dominio es la dirección de la casa, la URL es la ruta completa para llegar a una habitación específica dentro de esa casa. 8 | 9 | * **Nombre de dominio:** Es la parte principal de la dirección web, como "google.com" o "ejemplo.com". 10 | * **URL (Uniform Resource Locator):** Es la dirección completa de una página web, incluyendo el protocolo (http:// o https://), el nombre de dominio y a veces una ruta específica. Por ejemplo: [https://www.google.com/search/](https://www.google.com/search/). 11 | 12 | **¿Cómo funcionan los nombres de dominio?** 13 | 14 | Para que podamos escribir nombres de dominio en lugar de direcciones IP, existe un sistema llamado DNS (Domain Name System). El DNS funciona como una agenda telefónica gigante que traduce los nombres de dominio en direcciones IP. Cuando escribes un nombre de dominio en tu navegador, este envía una solicitud al servidor DNS para obtener la dirección IP correspondiente. Una vez que el servidor DNS encuentra la dirección IP, tu navegador puede cargar la página web. 15 | 16 | **Ejemplo:** 17 | 18 | Imagina que quieres visitar la página de inicio de Wikipedia. Escribes "[https://es.wikipedia.org/](https://es.wikipedia.org/)" en la barra de direcciones de tu navegador. 19 | 20 | * **https:** Indica que la conexión es segura. 21 | * **es.wikipedia.org:** Este es el nombre de dominio. 22 | * **/:** Indica que quieres acceder a la página principal del sitio. 23 | 24 | Cuando presionas Enter, tu navegador consulta al servidor DNS para obtener la dirección IP correspondiente a "es.wikipedia.org". Una vez que tiene la dirección IP, se conecta al servidor de Wikipedia y te muestra la página principal. 25 | 26 | **En resumen:** 27 | 28 | * **Nombre de dominio:** La dirección fácil de recordar de un sitio web. 29 | * **URL:** La dirección completa de una página específica dentro de un sitio web. 30 | * **DNS:** El sistema que traduce los nombres de dominio en direcciones IP. 31 | 32 | **¿Por qué son importantes los nombres de dominio?** 33 | 34 | * **Facilidad de uso:** Son más fáciles de recordar que las direcciones IP. 35 | * **Identidad de marca:** Un buen nombre de dominio puede ayudar a construir una marca fuerte. 36 | * **SEO:** Los nombres de dominio pueden influir en el posicionamiento de un sitio web en los motores de búsqueda. -------------------------------------------------------------------------------- /1. Internet/6.Qué es el Hosting.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es el Hosting? 2 | 3 | Imagina que tienes un sitio web, una tienda online, un blog o cualquier otro tipo de contenido digital que quieres que otras personas puedan ver en internet. Para que tu contenido esté disponible para cualquier persona en cualquier lugar del mundo, necesitas un lugar donde almacenar todos los archivos, imágenes, videos, y bases de datos que componen tu sitio web. Ese lugar es lo que llamamos "hosting" o "alojamiento web". 4 | 5 | ### Funcionamiento del Hosting 6 | 7 | El hosting funciona mediante la prestación de espacio en un servidor. Un servidor es una potente computadora que está siempre conectada a internet, diseñada específicamente para almacenar y gestionar los datos de los sitios web. Cuando alguien quiere visitar tu sitio web, su navegador envía una solicitud al servidor donde está alojado tu sitio, y este servidor responde enviando los archivos necesarios para mostrar tu página. 8 | 9 | ### Tipos de Hosting 10 | 11 | Existen varios tipos de hosting, cada uno con características y capacidades diferentes. Aquí te explico los más comunes: 12 | 13 | #### 1. **Hosting Compartido:** 14 | - **Descripción:** En este tipo de hosting, múltiples sitios web comparten los recursos de un solo servidor. 15 | - **Ventajas:** Es económico y fácil de gestionar, ideal para sitios web pequeños o personales. 16 | - **Desventajas:** El rendimiento puede verse afectado si otros sitios en el mismo servidor consumen muchos recursos. 17 | 18 | #### 2. **VPS (Servidor Privado Virtual):** 19 | - **Descripción:** Un VPS es una partición virtual dentro de un servidor físico, donde se reserva una cantidad específica de recursos para tu sitio. 20 | - **Ventajas:** Ofrece más control y recursos dedicados comparado con el hosting compartido, adecuado para sitios web de tamaño medio. 21 | - **Desventajas:** Requiere más conocimientos técnicos y es más costoso que el hosting compartido. 22 | 23 | #### 3. **Hosting Dedicado:** 24 | - **Descripción:** En este tipo, tienes un servidor completo para ti solo. 25 | - **Ventajas:** Máximo control, seguridad y rendimiento, ideal para sitios web grandes y de alto tráfico. 26 | - **Desventajas:** Es la opción más costosa y requiere conocimientos avanzados de administración de servidores. 27 | 28 | #### 4. **Hosting en la Nube (Cloud Hosting):** 29 | - **Descripción:** Utiliza una red de servidores en la nube para distribuir los recursos necesarios. 30 | - **Ventajas:** Escalabilidad, alta disponibilidad y flexibilidad, puedes ajustar los recursos según la demanda. 31 | - **Desventajas:** Puede ser más complejo de gestionar y el coste puede variar según el uso. 32 | 33 | ### Componentes de un Servicio de Hosting 34 | 35 | Un servicio de hosting incluye varios componentes esenciales: 36 | 37 | - **Espacio en Disco:** La cantidad de almacenamiento disponible para tus archivos y bases de datos. 38 | - **Ancho de Banda:** La cantidad de datos que pueden ser transferidos entre el servidor y los usuarios en un periodo de tiempo determinado. 39 | - **Cuentas de Correo Electrónico:** Algunas empresas de hosting ofrecen cuentas de correo asociadas a tu dominio. 40 | - **Soporte Técnico:** Ayuda disponible para resolver problemas técnicos o consultas sobre tu servicio de hosting. 41 | - **Seguridad:** Medidas como certificados SSL, copias de seguridad automáticas y protección contra malware. 42 | 43 | ### Importancia del Hosting 44 | 45 | El hosting es crucial porque determina la disponibilidad, velocidad y seguridad de tu sitio web. Un buen servicio de hosting asegura que tu sitio esté siempre accesible, cargue rápidamente y esté protegido contra posibles amenazas. 46 | 47 | ### Selección del Hosting Adecuado 48 | 49 | Elegir el hosting adecuado depende de varios factores, como el tipo de sitio web que tienes, el tráfico que esperas recibir, tu presupuesto y tu nivel de conocimiento técnico. Es importante evaluar y comparar diferentes proveedores de hosting para encontrar el que mejor se adapte a tus necesidades. 50 | 51 | ### Conclusión 52 | 53 | En resumen, el hosting es el servicio que permite que tu sitio web esté disponible en internet. Es el espacio donde se almacenan todos los componentes de tu sitio y el servidor que responde a las solicitudes de los usuarios para que puedan ver tu contenido. Hay diferentes tipos de hosting disponibles, cada uno adecuado para diferentes necesidades y presupuestos, y es crucial elegir el correcto para asegurar el rendimiento y la seguridad de tu sitio web. -------------------------------------------------------------------------------- /2.Java/1.Que es java.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es Java? 2 | 3 | Java es un lenguaje de programación de propósito general, orientado a objetos y concurrente, diseñado para tener la menor cantidad de dependencias posibles de implementación. Esto significa que el código escrito en Java puede ejecutarse en cualquier plataforma que soporte Java sin necesidad de ser recompilado. Java es conocido por su portabilidad, lo que significa que "escribe una vez, corre en cualquier lugar" (Write Once, Run Anywhere - WORA). Esta característica se debe a que el código Java se compila en bytecode, que puede ejecutarse en cualquier máquina virtual Java (JVM), independientemente de la arquitectura subyacente. 4 | 5 | ### ¿Cuándo y por quién fue creado? 6 | 7 | Java fue desarrollado originalmente por Sun Microsystems en 1991, bajo el nombre de proyecto "Oak". El creador principal de Java es James Gosling, un ingeniero canadiense, junto con su equipo en Sun Microsystems. En 1995, Oak fue renombrado a Java y lanzado públicamente como Java 1.0. Desde entonces, Java ha pasado por varias versiones y actualizaciones, mejorando en funcionalidad, rendimiento y seguridad. 8 | 9 | ### Función actual de Java 10 | 11 | Java sigue siendo uno de los lenguajes de programación más populares y utilizados en el mundo. Su versatilidad y robustez lo hacen ideal para una amplia gama de aplicaciones, desde pequeñas aplicaciones móviles hasta grandes sistemas empresariales y aplicaciones distribuidas. Java es el lenguaje principal para el desarrollo de aplicaciones Android, y es muy utilizado en el desarrollo de sistemas empresariales gracias a su capacidad de manejar transacciones, seguridad y alta disponibilidad. 12 | 13 | Algunas de las funciones actuales de Java incluyen: 14 | 15 | 1. **Desarrollo de aplicaciones empresariales:** Java es ampliamente utilizado en la creación de aplicaciones empresariales robustas que requieren escalabilidad, seguridad y transacciones distribuidas. 16 | 17 | 2. **Desarrollo de aplicaciones móviles:** Java es el lenguaje principal utilizado en el desarrollo de aplicaciones Android, el sistema operativo móvil más popular del mundo. 18 | 19 | 3. **Desarrollo web:** Con frameworks como Spring, Java es una opción popular para el desarrollo de aplicaciones web de gran escala. 20 | 21 | 4. **Aplicaciones científicas:** Debido a su rendimiento y manejo de grandes volúmenes de datos, Java se utiliza en aplicaciones científicas que requieren cálculos complejos y precisos. 22 | 23 | 5. **Internet de las cosas (IoT):** Java también se utiliza en dispositivos embebidos y aplicaciones IoT debido a su capacidad de ejecutarse en diferentes tipos de hardware. 24 | 25 | ### Compañías que utilizan Java 26 | 27 | Numerosas compañías en todo el mundo utilizan Java en sus sistemas y servicios debido a su estabilidad, seguridad y escalabilidad. Algunas de las más notables incluyen: 28 | 29 | 1. **Google:** Utiliza Java principalmente para el desarrollo de aplicaciones Android, así como en algunos de sus servicios backend. 30 | 31 | 2. **Amazon:** Utiliza Java en muchas de sus aplicaciones y servicios, incluyendo AWS, donde se ejecutan múltiples aplicaciones basadas en Java. 32 | 33 | 3. **Netflix:** La infraestructura de backend de Netflix utiliza Java para manejar la entrega de contenido a millones de usuarios en todo el mundo. 34 | 35 | 4. **Twitter:** Inicialmente construido con Ruby on Rails, Twitter migró gran parte de su infraestructura a Java debido a su rendimiento y escalabilidad. 36 | 37 | 5. **LinkedIn:** Usa Java para manejar la mayoría de sus servicios backend, incluyendo la infraestructura de búsqueda y recomendaciones. 38 | 39 | 6. **Oracle:** Después de adquirir Sun Microsystems en 2010, Oracle se convirtió en el principal mantenedor de Java. Utiliza Java en muchos de sus productos y servicios, incluidas sus soluciones empresariales. 40 | 41 | ### Conclusión 42 | 43 | Java es un lenguaje de programación que ha resistido la prueba del tiempo, permaneciendo relevante y ampliamente utilizado durante más de dos décadas. Su capacidad de ser ejecutado en múltiples plataformas, junto con su robustez y escalabilidad, lo ha convertido en una herramienta indispensable en el mundo del desarrollo de software. Desde aplicaciones móviles hasta grandes sistemas empresariales, Java sigue siendo una fuerza dominante en la industria tecnológica. -------------------------------------------------------------------------------- /2.Java/3.Condicionales simples y multiples.md: -------------------------------------------------------------------------------- 1 | # Condicionales simples y multiples en Java 2 | 3 | Los condicionales son una de las estructuras fundamentales en programación, que permiten tomar decisiones en función de si una condición se cumple o no. En Java, como en muchos otros lenguajes de programación, los condicionales permiten que un programa ejecute diferentes bloques de código en función del valor de ciertas expresiones lógicas. Vamos a desglosar cada uno de estos conceptos: 4 | 5 | ### 1. **Condicional `IF`** 6 | 7 | El condicional `if` en Java se utiliza para ejecutar un bloque de código solo si una condición específica es verdadera. Si la condición es falsa, el bloque de código dentro del `if` simplemente se omite. 8 | 9 | **Sintaxis:** 10 | ```java 11 | if (condición) { 12 | // Código a ejecutar si la condición es verdadera 13 | } 14 | ``` 15 | 16 | **Ejemplo:** 17 | ```java 18 | int edad = 18; 19 | 20 | if (edad >= 18) { 21 | System.out.println("Eres mayor de edad."); 22 | } 23 | ``` 24 | En este ejemplo, la condición `edad >= 18` se evalúa como verdadera, por lo tanto, el programa imprimirá "Eres mayor de edad." 25 | 26 | ### 2. **Condicional `IF` + `ELSE`** 27 | 28 | El condicional `if-else` es una extensión del `if`. Aquí, si la condición del `if` es verdadera, se ejecuta un bloque de código, pero si es falsa, se ejecuta otro bloque de código dentro del `else`. 29 | 30 | **Sintaxis:** 31 | ```java 32 | if (condición) { 33 | // Código a ejecutar si la condición es verdadera 34 | } else { 35 | // Código a ejecutar si la condición es falsa 36 | } 37 | ``` 38 | 39 | **Ejemplo:** 40 | ```java 41 | int edad = 16; 42 | 43 | if (edad >= 18) { 44 | System.out.println("Eres mayor de edad."); 45 | } else { 46 | System.out.println("Eres menor de edad."); 47 | } 48 | ``` 49 | En este caso, como `edad` es 16, la condición `edad >= 18` es falsa, por lo que el programa imprimirá "Eres menor de edad." 50 | 51 | ### 3. **Condicionales Múltiples: `IF`, `ELSE IF`, `ELSE`** 52 | 53 | A veces, se necesita evaluar múltiples condiciones de forma secuencial. En estos casos, se utiliza `else if` para agregar más condiciones después de un `if`. Si ninguna de las condiciones se cumple, se ejecuta el bloque de código en el `else`. 54 | 55 | **Sintaxis:** 56 | ```java 57 | if (condición1) { 58 | // Código a ejecutar si la condición1 es verdadera 59 | } else if (condición2) { 60 | // Código a ejecutar si la condición2 es verdadera 61 | } else if (condición3) { 62 | // Código a ejecutar si la condición3 es verdadera 63 | } else { 64 | // Código a ejecutar si ninguna de las condiciones anteriores es verdadera 65 | } 66 | ``` 67 | 68 | **Ejemplo:** 69 | ```java 70 | int edad = 15; 71 | 72 | if (edad >= 18) { 73 | System.out.println("Eres mayor de edad."); 74 | } else if (edad >= 13) { 75 | System.out.println("Eres adolescente."); 76 | } else if (edad >= 6) { 77 | System.out.println("Eres un niño."); 78 | } else { 79 | System.out.println("Eres un infante."); 80 | } 81 | ``` 82 | Aquí, el programa evalúa cada condición en secuencia: 83 | - `edad >= 18` es falsa. 84 | - `edad >= 13` es verdadera, por lo que se imprime "Eres adolescente" y se omiten las siguientes condiciones. 85 | 86 | ### 4. **¿Cómo funcionan los condicionales en Java?** 87 | 88 | En Java, los condicionales se basan en expresiones booleanas, es decir, expresiones que se evalúan como verdaderas (`true`) o falsas (`false`). Estas expresiones pueden incluir comparaciones, como `==`, `!=`, `<`, `>`, `<=`, `>=`, y operadores lógicos, como `&&` (AND) y `||` (OR). 89 | 90 | ### 5. **Aplicaciones Prácticas en Java** 91 | 92 | Los condicionales se utilizan en diversas situaciones, como controlar el flujo del programa, validar datos de entrada, o decidir qué acción tomar en base a ciertas condiciones. Aquí tienes un ejemplo práctico de uso en Java: 93 | 94 | **Ejemplo Completo:** 95 | ```java 96 | public class EjemploCondicionales { 97 | public static void main(String[] args) { 98 | int hora = 14; 99 | 100 | if (hora < 12) { 101 | System.out.println("Buenos días."); 102 | } else if (hora < 18) { 103 | System.out.println("Buenas tardes."); 104 | } else { 105 | System.out.println("Buenas noches."); 106 | } 107 | } 108 | } 109 | ``` 110 | En este ejemplo: 111 | - Si `hora` es menor que 12, el programa imprime "Buenos días." 112 | - Si `hora` es menor que 18 pero mayor o igual a 12, imprime "Buenas tardes." 113 | - Si `hora` es mayor o igual a 18, imprime "Buenas noches." 114 | 115 | ### Resumen: 116 | - **`if`**: Evalúa una condición; si es verdadera, ejecuta un bloque de código. 117 | - **`if-else`**: Evalúa una condición; si es verdadera, ejecuta un bloque de código, si es falsa, ejecuta otro. 118 | - **`if else-if else`**: Permite evaluar múltiples condiciones en secuencia y ejecutar el bloque correspondiente al primer `if` o `else if` verdadero, o ejecutar el `else` si ninguna condición se cumple. 119 | 120 | Estos condicionales permiten que el programa responda de manera dinámica a diferentes situaciones, haciendo que tu código sea más flexible y poderoso. -------------------------------------------------------------------------------- /2.Java/4.Condicional Switch.md: -------------------------------------------------------------------------------- 1 | # Condicional Switch en Java 2 | 3 | El condicional `switch` en Java es una estructura de control que permite ejecutar diferentes bloques de código según el valor de una expresión. Es una alternativa al uso de múltiples sentencias `if-else` cuando se necesita comparar una variable con varios valores posibles. El `switch` es más legible y, en algunos casos, más eficiente que una cadena de `if-else`. 4 | 5 | ### Estructura del `switch` 6 | 7 | La estructura básica de un `switch` es la siguiente: 8 | 9 | ```java 10 | switch (expresión) { 11 | case valor1: 12 | // Código a ejecutar si expresión == valor1 13 | break; 14 | case valor2: 15 | // Código a ejecutar si expresión == valor2 16 | break; 17 | // Más casos... 18 | default: 19 | // Código a ejecutar si expresión no coincide con ningún valor 20 | } 21 | ``` 22 | 23 | ### Componentes del `switch` 24 | 25 | 1. **Expresión**: Es el valor que se evalúa y se compara con cada uno de los casos (`case`). Debe ser de un tipo que permita comparaciones, como `int`, `char`, `String`, entre otros. 26 | 27 | 2. **Casos (`case`)**: Cada caso representa un valor posible que la expresión puede tomar. Si la expresión coincide con el valor de un `case`, el bloque de código asociado a ese caso se ejecuta. 28 | 29 | 3. **Sentencia `break`**: Se utiliza para salir del `switch` una vez que se ha ejecutado un caso. Sin el `break`, la ejecución continuará con el siguiente caso, lo que se conoce como *fall-through*. Aunque a veces se desea este comportamiento, es común usar `break` para evitar la ejecución no deseada de otros casos. 30 | 31 | 4. **Caso por defecto (`default`)**: Es un bloque de código que se ejecuta si la expresión no coincide con ningún caso. Es opcional, pero es buena práctica incluirlo para manejar valores inesperados. 32 | 33 | ### Funcionamiento del `switch` 34 | 35 | Cuando se encuentra un `switch`, el programa evalúa la expresión y la compara con los valores de cada `case`. Si encuentra un `case` que coincide con el valor de la expresión, ejecuta el bloque de código correspondiente. Si no encuentra coincidencia y existe un `default`, ejecuta el bloque de `default`. 36 | 37 | ### Ejemplos de uso en Java 38 | 39 | **Ejemplo 1: Día de la semana** 40 | 41 | ```java 42 | public class SwitchExample { 43 | public static void main(String[] args) { 44 | int day = 3; 45 | String dayName; 46 | 47 | switch (day) { 48 | case 1: 49 | dayName = "Lunes"; 50 | break; 51 | case 2: 52 | dayName = "Martes"; 53 | break; 54 | case 3: 55 | dayName = "Miércoles"; 56 | break; 57 | case 4: 58 | dayName = "Jueves"; 59 | break; 60 | case 5: 61 | dayName = "Viernes"; 62 | break; 63 | case 6: 64 | dayName = "Sábado"; 65 | break; 66 | case 7: 67 | dayName = "Domingo"; 68 | break; 69 | default: 70 | dayName = "Día no válido"; 71 | break; 72 | } 73 | 74 | System.out.println("El día de la semana es: " + dayName); 75 | } 76 | } 77 | ``` 78 | 79 | En este ejemplo, la variable `day` se evalúa y, dado que su valor es `3`, el programa imprime "El día de la semana es: Miércoles". 80 | 81 | **Ejemplo 2: Evaluación de calificaciones** 82 | 83 | ```java 84 | public class SwitchExample { 85 | public static void main(String[] args) { 86 | char grade = 'B'; 87 | 88 | switch (grade) { 89 | case 'A': 90 | System.out.println("Excelente!"); 91 | break; 92 | case 'B': 93 | System.out.println("Bien hecho!"); 94 | break; 95 | case 'C': 96 | System.out.println("Bueno!"); 97 | break; 98 | case 'D': 99 | System.out.println("Puedes mejorar!"); 100 | break; 101 | case 'F': 102 | System.out.println("Reprobado!"); 103 | break; 104 | default: 105 | System.out.println("Calificación no válida"); 106 | break; 107 | } 108 | } 109 | } 110 | ``` 111 | 112 | Aquí, dependiendo de la calificación (`grade`), se imprime un mensaje diferente. En este caso, con `grade = 'B'`, el programa imprime "Bien hecho!". 113 | 114 | ### Consideraciones 115 | 116 | 1. **Fall-Through**: Si se omite la sentencia `break` en un `case`, el programa continuará ejecutando los casos siguientes, incluso si estos no coinciden con el valor de la expresión. Esto se puede utilizar intencionadamente en ciertos casos, pero suele ser un error común cuando se olvida incluir el `break`. 117 | 118 | ```java 119 | switch (grade) { 120 | case 'A': 121 | case 'B': 122 | System.out.println("Bien hecho!"); 123 | break; 124 | // Otros casos... 125 | } 126 | ``` 127 | 128 | En este ejemplo, si `grade` es 'A' o 'B', el mismo mensaje "Bien hecho!" se imprimirá para ambos casos. 129 | 130 | 2. **Tipos de Datos Soportados**: En versiones anteriores de Java, el `switch` solo funcionaba con tipos primitivos como `int` y `char`. A partir de Java 7, se introdujo soporte para `String`, lo que amplió considerablemente la utilidad de `switch`. 131 | 132 | 3. **Performance**: En algunos casos, un `switch` puede ser más eficiente que una cadena de `if-else`, especialmente si hay muchos casos, ya que algunos compiladores optimizan los `switch` usando estructuras como tablas de saltos. 133 | 134 | ### Conclusión 135 | 136 | El `switch` es una herramienta poderosa en Java para simplificar la lógica de selección múltiple. Es especialmente útil cuando se necesita comparar una variable con muchos valores posibles, mejorando la legibilidad y, en algunos casos, el rendimiento del código. -------------------------------------------------------------------------------- /2.Java/5.Bucle While.md: -------------------------------------------------------------------------------- 1 | # Bucle While en Java 2 | 3 | La estructura repetitiva `while` en Java es un tipo de bucle que se utiliza para ejecutar un bloque de código de manera repetitiva mientras se cumpla una condición específica. Esta condición se evalúa **antes** de cada iteración, y si es verdadera, el bloque de código se ejecuta. Una vez que la condición se evalúa como falsa, el bucle termina y la ejecución del programa continúa con la siguiente instrucción después del bucle. 4 | 5 | ### Sintaxis de la estructura `while` 6 | 7 | ```java 8 | while (condición) { 9 | // Bloque de código a ejecutar mientras la condición sea verdadera 10 | } 11 | ``` 12 | 13 | ### Explicación detallada 14 | 1. **Condición**: Es una expresión booleana (es decir, se evalúa como `true` o `false`). Mientras esta condición sea verdadera (`true`), el bloque de código dentro del `while` seguirá ejecutándose. 15 | 16 | 2. **Bloque de código**: Es el conjunto de instrucciones que se ejecutarán repetidamente mientras la condición sea verdadera. Si la condición se evalúa como falsa desde el principio, el bloque de código nunca se ejecuta. 17 | 18 | 3. **Punto de salida**: Es crucial asegurarse de que la condición eventualmente se vuelva falsa. De lo contrario, se creará un bucle infinito que podría bloquear o colgar la aplicación. 19 | 20 | ### Ejemplo básico: Contador 21 | 22 | Este es un ejemplo simple que muestra cómo funciona un bucle `while` en Java. 23 | 24 | ```java 25 | public class EjemploWhile { 26 | public static void main(String[] args) { 27 | int contador = 1; // Inicialización de la variable 28 | 29 | while (contador <= 5) { // La condición a evaluar 30 | System.out.println("Contador: " + contador); // Acción a realizar en cada iteración 31 | contador++; // Incremento de la variable 32 | } 33 | } 34 | } 35 | ``` 36 | 37 | #### Explicación del código: 38 | - **Variable contador**: Es la variable que controla el bucle y se inicializa con un valor de 1. 39 | - **Condición**: `contador <= 5` es la condición que se evalúa antes de cada iteración. El bucle continuará mientras el valor de `contador` sea menor o igual a 5. 40 | - **Cuerpo del bucle**: Se imprime el valor actual de `contador` y luego se incrementa en 1 en cada iteración usando `contador++`. 41 | 42 | El resultado de este código será: 43 | ``` 44 | Contador: 1 45 | Contador: 2 46 | Contador: 3 47 | Contador: 4 48 | Contador: 5 49 | ``` 50 | 51 | Una vez que `contador` alcanza 6, la condición `contador <= 5` se evalúa como falsa y el bucle termina. 52 | 53 | ### Ejemplo práctico: Suma de números ingresados por el usuario 54 | 55 | Este ejemplo muestra cómo un bucle `while` puede utilizarse para sumar números ingresados por el usuario hasta que se ingrese un valor negativo. 56 | 57 | ```java 58 | import java.util.Scanner; 59 | 60 | public class SumaNumeros { 61 | public static void main(String[] args) { 62 | Scanner scanner = new Scanner(System.in); 63 | int suma = 0; 64 | int numero; 65 | 66 | System.out.println("Introduce un número para sumar (introduce un número negativo para terminar):"); 67 | 68 | numero = scanner.nextInt(); // Primer número ingresado 69 | 70 | while (numero >= 0) { // El bucle se repite mientras el número sea positivo 71 | suma += numero; // Acumulamos la suma 72 | System.out.println("Introduce otro número (o un número negativo para terminar):"); 73 | numero = scanner.nextInt(); // Se pide otro número al usuario 74 | } 75 | 76 | System.out.println("La suma total es: " + suma); 77 | } 78 | } 79 | ``` 80 | 81 | #### Explicación del código: 82 | - **Entrada del usuario**: El programa solicita al usuario que ingrese un número. 83 | - **Condición del bucle**: Mientras el número ingresado sea mayor o igual a 0, el bucle sigue repitiéndose. 84 | - **Acumulación de la suma**: El número ingresado se suma a la variable `suma` en cada iteración. 85 | - **Punto de salida**: Si el usuario ingresa un número negativo, la condición se vuelve falsa y el bucle se detiene, mostrando el resultado final. 86 | 87 | ### Consideraciones importantes 88 | - **Bucle infinito**: Si la condición del `while` nunca se vuelve falsa, el bucle se ejecutará indefinidamente, creando un bucle infinito. Ejemplo: 89 | ```java 90 | while (true) { 91 | System.out.println("Esto es un bucle infinito"); 92 | } 93 | ``` 94 | En este caso, el programa nunca se detendrá a menos que se fuerce su cierre. 95 | 96 | - **Actualización de la condición**: Es importante asegurarse de que el valor utilizado en la condición cambie en algún momento dentro del bucle para evitar un bucle infinito. En los ejemplos anteriores, esto se logra incrementando el valor de `contador` o solicitando una nueva entrada del usuario. 97 | 98 | ### Conclusión 99 | La estructura `while` es una herramienta poderosa en programación para manejar situaciones en las que no se sabe de antemano cuántas veces se necesitará repetir un bloque de código. Su flexibilidad la hace ideal para situaciones en las que el número de iteraciones depende de una condición dinámica. -------------------------------------------------------------------------------- /2.Java/6.Bucles For.md: -------------------------------------------------------------------------------- 1 | # Estructuras Repetitivas: FOR en Java 2 | 3 | La estructura repetitiva `FOR` es una de las más utilizadas en programación cuando se necesita realizar un ciclo controlado por un contador. A diferencia de la estructura `while`, que permite tanto centinelas como contadores, el `for` está diseñado específicamente para iteraciones donde se conoce de antemano cuántas veces se va a repetir un bloque de código. 4 | 5 | ### Componentes del FOR 6 | 7 | El ciclo `for` se compone de tres partes clave: 8 | 9 | 1. **Inicialización**: Aquí se inicializa la variable que servirá como contador. Esta acción solo se ejecuta una vez al comienzo del ciclo. 10 | 11 | ```java 12 | for (int i = 0; i < 10; i++) { 13 | // Código a ejecutar 14 | } 15 | ``` 16 | 17 | En este caso, la variable `i` se inicializa con el valor `0`. 18 | 19 | 2. **Condición**: Es una expresión que se evalúa antes de cada iteración. Mientras esta condición sea verdadera, el ciclo continuará ejecutándose. 20 | 21 | ```java 22 | for (int i = 0; i < 10; i++) { 23 | // Código a ejecutar 24 | } 25 | ``` 26 | 27 | La condición `i < 10` indica que el ciclo continuará mientras `i` sea menor que 10. 28 | 29 | 3. **Modificación**: Después de cada iteración, se ejecuta esta parte. Suele ser un incremento o decremento del contador. 30 | 31 | ```java 32 | for (int i = 0; i < 10; i++) { 33 | // Código a ejecutar 34 | } 35 | ``` 36 | 37 | Aquí, `i++` incrementa el valor de `i` en 1 al final de cada iteración. 38 | 39 | ### Ejemplos en Java 40 | 41 | **Ejemplo 1: Imprimir los números del 1 al 10** 42 | 43 | ```java 44 | public class EjemploFor { 45 | public static void main(String[] args) { 46 | for (int i = 1; i <= 10; i++) { 47 | System.out.println(i); 48 | } 49 | } 50 | } 51 | ``` 52 | 53 | Este código imprimirá los números del 1 al 10 en la consola. Observa cómo la condición `i <= 10` asegura que el ciclo se detenga cuando `i` llegue a 11. 54 | 55 | **Ejemplo 2: Recorrer un array** 56 | 57 | El `for` también es ideal para recorrer arrays, que son estructuras que veremos en profundidad más adelante. 58 | 59 | ```java 60 | public class RecorrerArray { 61 | public static void main(String[] args) { 62 | String[] nombres = {"Ana", "Luis", "Pedro", "Marta"}; 63 | 64 | for (int i = 0; i < nombres.length; i++) { 65 | System.out.println("Nombre: " + nombres[i]); 66 | } 67 | } 68 | } 69 | ``` 70 | 71 | En este caso, el ciclo `for` recorre todos los elementos del array `nombres`, imprimiendo cada uno en la consola. Fíjate en cómo se usa la propiedad `length` para asegurarse de que no se exceda el límite del array. 72 | 73 | ### ¿Por qué utilizar FOR? 74 | 75 | El ciclo `for` es la estructura más elegida cuando sabemos de antemano cuántas veces queremos que se ejecute un bloque de código. Su sintaxis compacta y clara facilita la legibilidad del código, especialmente en situaciones donde la iteración está controlada por un contador. Es la herramienta por excelencia cuando trabajamos con listas, arrays y otras colecciones en las que se necesita recorrer cada elemento. 76 | 77 | Conforme sigas practicando y profundizando en Java, verás que el `for` es un aliado fundamental, especialmente cuando empieces a trabajar con estructuras de datos más complejas. ¡Sigue explorando y practicando! -------------------------------------------------------------------------------- /2.Java/7.Vectores (Arrays).md: -------------------------------------------------------------------------------- 1 | # Vectores o Arrays en Java 2 | 3 | Los **vectores** o **arrays** en Java son una estructura de datos que permite almacenar múltiples valores del mismo tipo bajo un solo nombre, lo que facilita la organización y manipulación de datos. Cada elemento en un array se puede acceder mediante un índice, que comienza desde 0. A diferencia de las listas dinámicas, los arrays tienen un tamaño fijo: una vez declarados, no pueden cambiar su tamaño durante la ejecución del programa. 4 | 5 | ### Declaración de Arrays en Java 6 | 7 | Para declarar un array en Java, debes seguir la siguiente sintaxis básica: 8 | 9 | ```java 10 | tipo[] nombreArray; 11 | ``` 12 | 13 | Aquí: 14 | 15 | - **tipo**: Es el tipo de dato que almacenará el array (puede ser `int`, `double`, `char`, `String`, entre otros). 16 | - **nombreArray**: Es el nombre que le das al array. 17 | 18 | **Ejemplo de declaración:** 19 | 20 | ```java 21 | int[] numeros; // Declaración de un array de enteros. 22 | ``` 23 | 24 | ### Asignación de Memoria para el Array 25 | 26 | Una vez declarado, es necesario asignar memoria para el array. Esto se hace utilizando la palabra clave `new`, especificando el tamaño del array (es decir, cuántos elementos puede almacenar). La sintaxis es: 27 | 28 | ```java 29 | nombreArray = new tipo[tamaño]; 30 | ``` 31 | 32 | **Ejemplo de asignación:** 33 | 34 | ```java 35 | numeros = new int[5]; // Asignación de un array de 5 enteros. 36 | ``` 37 | 38 | El array `numeros` puede ahora almacenar 5 elementos de tipo `int`. Recuerda que el tamaño del array es fijo y no puede cambiar una vez definido. 39 | 40 | ### Declaración y Asignación Simultánea 41 | 42 | También es posible declarar y asignar el array en una sola línea: 43 | 44 | ```java 45 | int[] numeros = new int[5]; // Declaración y asignación en una sola línea. 46 | ``` 47 | 48 | ### Inicialización de Arrays 49 | 50 | Puedes inicializar un array con valores específicos durante su declaración: 51 | 52 | ```java 53 | int[] numeros = {10, 20, 30, 40, 50}; // Array con valores iniciales. 54 | ``` 55 | 56 | En este caso, el tamaño del array es determinado automáticamente según el número de elementos proporcionados. 57 | 58 | ### Acceso a los Elementos del Array 59 | 60 | Cada elemento en un array se accede usando su índice, que empieza desde 0 hasta `n-1`, donde `n` es el tamaño del array. Para acceder a un elemento, usa la siguiente sintaxis: 61 | 62 | ```java 63 | nombreArray[indice] 64 | ``` 65 | 66 | **Ejemplo:** 67 | 68 | ```java 69 | int primerNumero = numeros[0]; // Accede al primer elemento del array (valor 10). 70 | ``` 71 | 72 | ### Modificación de los Elementos del Array 73 | 74 | Puedes cambiar el valor de un elemento específico usando su índice: 75 | 76 | ```java 77 | numeros[2] = 100; // Cambia el valor en la posición 2 (antes era 30, ahora es 100). 78 | ``` 79 | 80 | ### Recorrido de Arrays 81 | 82 | Una de las operaciones más comunes con arrays es recorrerlos, ya sea para mostrar sus valores, calcular sumas, buscar elementos, etc. Esto se puede hacer usando estructuras repetitivas como `for` o `for-each`. 83 | 84 | **Ejemplo con `for`:** 85 | 86 | ```java 87 | for (int i = 0; i < numeros.length; i++) { 88 | System.out.println("Elemento en la posición " + i + ": " + numeros[i]); 89 | } 90 | ``` 91 | 92 | **Ejemplo con `for-each`:** 93 | 94 | ```java 95 | for (int numero : numeros) { 96 | System.out.println("Valor: " + numero); 97 | } 98 | ``` 99 | 100 | ### Ejemplo Completo en Java 101 | 102 | A continuación, un ejemplo completo que cubre declaración, asignación, inicialización y acceso a elementos en un array: 103 | 104 | ```java 105 | public class EjemploArray { 106 | public static void main(String[] args) { 107 | // Declaración y asignación del array 108 | int[] numeros = new int[5]; 109 | 110 | // Inicialización de elementos 111 | numeros[0] = 10; 112 | numeros[1] = 20; 113 | numeros[2] = 30; 114 | numeros[3] = 40; 115 | numeros[4] = 50; 116 | 117 | // Acceso y modificación de elementos 118 | System.out.println("Elemento en la posición 2: " + numeros[2]); // Imprime 30 119 | numeros[2] = 100; // Cambia el valor en la posición 2 120 | System.out.println("Nuevo valor en la posición 2: " + numeros[2]); // Imprime 100 121 | 122 | // Recorrido del array usando for 123 | System.out.println("Recorriendo el array:"); 124 | for (int i = 0; i < numeros.length; i++) { 125 | System.out.println("Elemento en la posición " + i + ": " + numeros[i]); 126 | } 127 | } 128 | } 129 | ``` 130 | 131 | ### Salida del Programa 132 | 133 | ``` 134 | Elemento en la posición 2: 30 135 | Nuevo valor en la posición 2: 100 136 | Recorriendo el array: 137 | Elemento en la posición 0: 10 138 | Elemento en la posición 1: 20 139 | Elemento en la posición 2: 100 140 | Elemento en la posición 3: 40 141 | Elemento en la posición 4: 50 142 | ``` 143 | 144 | ### Resumen 145 | 146 | - Los arrays en Java son estructuras de tamaño fijo que almacenan múltiples valores del mismo tipo. 147 | - Se declaran especificando el tipo de dato seguido de `[]`. 148 | - Se asigna memoria usando la palabra clave `new` y especificando el tamaño del array. 149 | - Los elementos del array se acceden y modifican usando su índice. 150 | - Es común recorrer arrays usando bucles `for` o `for-each`. 151 | 152 | Los arrays son fundamentales en la programación y son la base de estructuras de datos más avanzadas como listas, pilas y colas. -------------------------------------------------------------------------------- /2.Java/8.Matrices.md: -------------------------------------------------------------------------------- 1 | # Matrices en Java 2 | 3 | #### ¿Qué son las matrices? 4 | 5 | En programación, una matriz (o arreglo bidimensional) es una estructura de datos que permite almacenar elementos en un formato de tabla, con filas y columnas. Al igual que los vectores (arreglos unidimensionales), las matrices son contenedores de datos homogéneos (todos los elementos deben ser del mismo tipo), pero con la diferencia de que una matriz tiene dos dimensiones en lugar de una. 6 | 7 | Podemos imaginar una matriz como una hoja de cálculo o tabla, donde cada celda puede contener un valor. La principal característica es que las celdas se organizan en filas y columnas. 8 | 9 | #### Estructura de una Matriz 10 | 11 | Una matriz es un conjunto de elementos dispuestos en un formato de tabla. Por ejemplo: 12 | 13 | ```text 14 | 1 2 3 15 | 1 4 5 6 16 | 2 7 8 9 17 | ``` 18 | 19 | En el ejemplo anterior, tenemos una matriz de 2x3 (2 filas y 3 columnas). Cada posición en la matriz tiene un índice que corresponde a la fila y la columna, respectivamente. En Java, las matrices comienzan desde el índice 0, por lo que la primera fila y primera columna son `0`. 20 | 21 | #### Declaración de Matrices en Java 22 | 23 | En Java, declarar una matriz se hace especificando el tipo de datos, seguido de dos pares de corchetes (`[][]`) y el nombre de la matriz. Luego, podemos usar la palabra clave `new` para inicializar la matriz indicando el número de filas y columnas. 24 | 25 | **Sintaxis:** 26 | 27 | ```java 28 | tipoDeDato[][] nombreDeMatriz = new tipoDeDato[numFilas][numColumnas]; 29 | ``` 30 | 31 | **Ejemplo:** 32 | 33 | ```java 34 | int[][] matriz = new int[3][3]; // Matriz de enteros de 3x3 35 | ``` 36 | 37 | En este caso, hemos declarado una matriz de 3 filas y 3 columnas. 38 | 39 | #### Asignación de Valores a una Matriz 40 | 41 | Podemos asignar valores a las celdas de la matriz utilizando índices para especificar la fila y la columna. 42 | 43 | **Sintaxis:** 44 | 45 | ```java 46 | nombreDeMatriz[indiceFila][indiceColumna] = valor; 47 | ``` 48 | 49 | **Ejemplo:** 50 | 51 | ```java 52 | matriz[0][0] = 1; 53 | matriz[0][1] = 2; 54 | matriz[0][2] = 3; 55 | matriz[1][0] = 4; 56 | matriz[1][1] = 5; 57 | matriz[1][2] = 6; 58 | matriz[2][0] = 7; 59 | matriz[2][1] = 8; 60 | matriz[2][2] = 9; 61 | ``` 62 | 63 | Ahora la matriz se vería así: 64 | 65 | ```text 66 | 1 2 3 67 | 4 5 6 68 | 7 8 9 69 | ``` 70 | 71 | #### Declaración e Inicialización en un Solo Paso 72 | 73 | En lugar de declarar y luego asignar valores, podemos inicializar una matriz con valores directamente al declararla. 74 | 75 | **Ejemplo:** 76 | 77 | ```java 78 | int[][] matriz = { 79 | {1, 2, 3}, 80 | {4, 5, 6}, 81 | {7, 8, 9} 82 | }; 83 | ``` 84 | 85 | En este caso, la matriz ya se inicializa con los valores. 86 | 87 | #### Recorrido de una Matriz 88 | 89 | Para recorrer una matriz y acceder a cada elemento, se pueden utilizar bucles anidados. El primer bucle recorre las filas y el segundo recorre las columnas. 90 | 91 | **Ejemplo:** 92 | 93 | ```java 94 | for (int i = 0; i < matriz.length; i++) { // Recorre las filas 95 | for (int j = 0; j < matriz[i].length; j++) { // Recorre las columnas 96 | System.out.print(matriz[i][j] + " "); 97 | } 98 | System.out.println(); // Salto de línea al terminar cada fila 99 | } 100 | ``` 101 | 102 | Este código imprimirá: 103 | 104 | ```text 105 | 1 2 3 106 | 4 5 6 107 | 7 8 9 108 | ``` 109 | 110 | #### Matrices con Otros Tipos de Datos 111 | 112 | Las matrices no se limitan solo a enteros. Podemos crear matrices con otros tipos de datos, como `double`, `char`, o incluso objetos. 113 | 114 | **Ejemplo con `String`:** 115 | 116 | ```java 117 | String[][] nombres = { 118 | {"Ana", "Juan"}, 119 | {"Luis", "Sofía"} 120 | }; 121 | 122 | for (int i = 0; i < nombres.length; i++) { 123 | for (int j = 0; j < nombres[i].length; j++) { 124 | System.out.print(nombres[i][j] + " "); 125 | } 126 | System.out.println(); 127 | } 128 | ``` 129 | 130 | Salida: 131 | 132 | ```text 133 | Ana Juan 134 | Luis Sofía 135 | ``` 136 | 137 | ### Conclusión 138 | 139 | Las matrices son una poderosa herramienta para organizar y manipular datos en dos dimensiones. Permiten almacenar y acceder a datos de manera eficiente, siendo útiles en diversas aplicaciones, como el manejo de tablas, gráficos y más. Además, son esenciales en la programación orientada a objetos y en algoritmos más complejos. 140 | 141 | ¡Con esta base ya puedes comenzar a trabajar con matrices en tus proyectos en Java! -------------------------------------------------------------------------------- /2.Java/9.Funciones.md: -------------------------------------------------------------------------------- 1 | # Funciones en java 2 | 3 | Las **funciones**, también conocidas como **métodos** en Java, son bloques de código que realizan una tarea específica y que pueden ser invocados desde otras partes del programa. Las funciones permiten reutilizar código, mejorar la organización y facilitar el mantenimiento de aplicaciones. 4 | 5 | ### Estructura de una Función en Java 6 | 7 | Una función en Java tiene una estructura básica que incluye los siguientes elementos: 8 | 9 | 1. **Modificadores de acceso** (opcional): Determinan quién puede acceder a la función (ej. `public`, `private`, `protected`). 10 | 2. **Tipo de retorno**: Indica el tipo de dato que devuelve la función (ej. `int`, `String`, `void` si no retorna nada). 11 | 3. **Nombre de la función**: Debe ser representativo de lo que hace la función. Por convención, el nombre empieza con minúscula y sigue la notación camelCase. 12 | 4. **Parámetros** (opcional): Datos que la función puede recibir para procesarlos. 13 | 5. **Cuerpo de la función**: Contiene las instrucciones que se ejecutan cuando se llama a la función. 14 | 6. **Valor de retorno** (opcional): Si la función no es `void`, debe retornar un valor compatible con el tipo de retorno. 15 | 16 | ### Ejemplo Básico de una Función en Java 17 | 18 | Supongamos que queremos crear una función que sume dos números enteros: 19 | 20 | ```java 21 | public int sumar(int a, int b) { 22 | int resultado = a + b; 23 | return resultado; 24 | } 25 | ``` 26 | 27 | #### Explicación del código: 28 | 29 | - `public`: El modificador de acceso, que permite que la función sea accesible desde cualquier parte del programa. 30 | - `int`: El tipo de retorno, indicando que la función devolverá un número entero. 31 | - `sumar`: El nombre de la función. 32 | - `(int a, int b)`: Los parámetros, que son dos números enteros que se pasan a la función. 33 | - `int resultado = a + b;`: Dentro del cuerpo, se realiza la operación de suma y se almacena en una variable. 34 | - `return resultado;`: La función devuelve el valor almacenado en `resultado`. 35 | 36 | ### Invocación de la Función 37 | 38 | Para usar esta función, podrías hacerlo de la siguiente manera: 39 | 40 | ```java 41 | public class Main { 42 | public static void main(String[] args) { 43 | Main calculadora = new Main(); 44 | int resultado = calculadora.sumar(5, 3); 45 | System.out.println("El resultado es: " + resultado); 46 | } 47 | 48 | public int sumar(int a, int b) { 49 | return a + b; 50 | } 51 | } 52 | ``` 53 | 54 | ### Tipos de Funciones en Java 55 | 56 | 1. **Funciones sin retorno (`void`)**: 57 | Estas funciones no devuelven ningún valor. Solo ejecutan un bloque de código. 58 | 59 | Ejemplo: 60 | 61 | ```java 62 | public void saludar() { 63 | System.out.println("¡Hola, bienvenido!"); 64 | } 65 | ``` 66 | 67 | Invocación: 68 | 69 | ```java 70 | saludar(); 71 | ``` 72 | 73 | 2. **Funciones con retorno**: 74 | Estas funciones devuelven un valor específico después de realizar sus operaciones. 75 | 76 | Ejemplo: 77 | 78 | ```java 79 | public String obtenerSaludo(String nombre) { 80 | return "Hola, " + nombre; 81 | } 82 | ``` 83 | 84 | Invocación: 85 | 86 | ```java 87 | String saludo = obtenerSaludo("Agustín"); 88 | System.out.println(saludo); 89 | ``` 90 | 91 | 3. **Funciones con parámetros**: 92 | Estas funciones reciben datos que luego procesan. 93 | 94 | Ejemplo: 95 | 96 | ```java 97 | public int multiplicar(int x, int y) { 98 | return x * y; 99 | } 100 | ``` 101 | 102 | Invocación: 103 | 104 | ```java 105 | int producto = multiplicar(4, 5); 106 | System.out.println(producto); 107 | ``` 108 | 109 | 4. **Sobrecarga de funciones**: 110 | Es posible definir varias funciones con el mismo nombre pero diferentes parámetros, lo que se llama sobrecarga. 111 | 112 | Ejemplo: 113 | 114 | ```java 115 | public int sumar(int a, int b) { 116 | return a + b; 117 | } 118 | 119 | public double sumar(double a, double b) { 120 | return a + b; 121 | } 122 | ``` 123 | 124 | Dependiendo de los tipos de datos que pases, se ejecutará la versión adecuada. 125 | 126 | ### Importancia de las Funciones 127 | 128 | - **Reutilización de código**: Puedes llamar una función varias veces sin reescribir el código. 129 | - **Mantenibilidad**: El código está mejor organizado y es más fácil de leer. 130 | - **Modularidad**: Divides tu programa en pequeños bloques que se encargan de tareas específicas. 131 | 132 | Las funciones son una parte fundamental de cualquier lenguaje de programación y permiten construir aplicaciones de forma más eficiente y ordenada. -------------------------------------------------------------------------------- /3.Java POO/11.POO Programación Orientada a Objetos.md: -------------------------------------------------------------------------------- 1 | # Programación Orientada a Objetos 2 | 3 | La Programación Orientada a Objetos (POO) es un paradigma de programación que nos permite modelar nuestro código a partir de la forma en la que percibimos el mundo real, utilizando objetos que representan entidades, conceptos o elementos. Este enfoque nos facilita la organización y estructuración del código en proyectos complejos, haciendo que sea más fácil de mantener, escalar y entender. 4 | 5 | **¿Qué es un paradigma?** Un paradigma es un conjunto de conceptos, métodos y reglas que determinan cómo resolver problemas dentro de un campo específico. En el caso de la programación, existen varios paradigmas como el estructurado, funcional y orientado a objetos, cada uno con su propio enfoque. La POO, en particular, se centra en la creación de objetos que contienen tanto datos como comportamientos. 6 | 7 | En la POO, un **objeto** es una instancia de una **clase**, que puede considerarse como un plano o plantilla que define las características y comportamientos que el objeto tendrá. Por ejemplo, si pensamos en un coche, podríamos decir que la clase es el concepto general de un coche, mientras que un coche específico (como tu coche) es un objeto. 8 | 9 | La POO se basa en cuatro pilares fundamentales que permiten esta abstracción y modelado del mundo real: 10 | 11 | ### 1. **Abstracción** 12 | La abstracción es la capacidad de enfocarse en los aspectos más relevantes de un objeto, ignorando los detalles innecesarios. En otras palabras, nos permite simplificar la complejidad al definir solo los atributos y comportamientos esenciales de un objeto para el problema que estamos resolviendo. Siguiendo con el ejemplo del coche, en un sistema de gestión de vehículos, podemos abstraerlo definiendo solo atributos como "marca", "modelo" y "color", y comportamientos como "acelerar" o "frenar", sin necesidad de modelar detalles irrelevantes como el color del tapizado. 13 | 14 | ### 2. **Encapsulamiento** 15 | El encapsulamiento es la propiedad que nos permite ocultar los detalles internos de un objeto y exponer solo lo necesario a través de interfaces bien definidas. Esto se logra controlando el acceso a los atributos y métodos mediante modificadores de visibilidad (como `public`, `private` y `protected`). Por ejemplo, si tienes una cuenta bancaria como objeto, los detalles sobre cómo se calcula el saldo o cómo se gestionan las transacciones están encapsulados y no son accesibles directamente. Solo se expone un método como "consultar saldo", garantizando la seguridad y consistencia de los datos. 16 | 17 | ### 3. **Herencia** 18 | La herencia permite crear nuevas clases basadas en clases existentes, aprovechando y reutilizando su código. Esto facilita la creación de jerarquías de clases, donde las clases derivadas heredan atributos y comportamientos de la clase base, pero también pueden añadir o modificar funcionalidades. Siguiendo con el ejemplo del coche, podrías tener una clase base "Vehículo" con atributos comunes como "velocidad" y "capacidad de pasajeros", y luego derivar clases como "Coche" y "Camión" que heredan esas propiedades pero añaden otras específicas. 19 | 20 | ### 4. **Polimorfismo** 21 | El polimorfismo es la capacidad de que un mismo método o acción se comporte de diferentes maneras según el objeto que lo utilice. Existen dos tipos de polimorfismo: polimorfismo en tiempo de compilación (sobrecarga) y polimorfismo en tiempo de ejecución (sobreescritura). Esto es crucial en la flexibilidad y reutilización del código. Por ejemplo, si tienes un método llamado "mover" en la clase base "Vehículo", este podría comportarse de manera distinta si el objeto es un "Coche" o un "Barco", aunque el método tenga el mismo nombre. 22 | 23 | La POO permite que las soluciones de software se desarrollen de manera más intuitiva y natural, ya que se alinean con nuestra forma de pensar sobre el mundo a través de objetos y relaciones entre ellos. Este paradigma no solo facilita la construcción de programas modulares y escalables, sino que también promueve la reutilización y organización del código, contribuyendo a la eficiencia en el desarrollo de software. -------------------------------------------------------------------------------- /3.Java POO/12.Que son las clases y como crearla.md: -------------------------------------------------------------------------------- 1 | # ¿Qué son las clases? ¿Cómo crear una? 2 | 3 | Una clase es el concepto central en la programación orientada a objetos (POO) y representa la definición de un tipo de entidad o conjunto de objetos que comparten características comunes. Para entender mejor qué es una clase, podemos imaginarla como un plano o un molde en el que se especifican las propiedades y comportamientos que tendrán todos los objetos creados a partir de ella. 4 | 5 | ### ¿Qué es una clase? 6 | 7 | En términos teóricos, una clase es una **abstracción** que agrupa atributos que describen el estado y características comunes de un conjunto de objetos. Si pensamos en un entorno cotidiano, podríamos ver la clase como una idea o modelo que encapsula lo esencial de un concepto. Por ejemplo, la clase "Persona" podría englobar características como "nombre", "edad", "género", y "altura". Es decir, cualquier persona individual creada a partir de esta clase compartiría estas características, aunque con valores específicos para cada objeto. 8 | 9 | ### Características de una clase: 10 | 11 | 1. **Abstracción**: Una clase no es un objeto en sí mismo; es una representación abstracta de algo que puede existir en el mundo real o en un sistema conceptual. Te permite definir los atributos generales de un tipo de entidad sin preocuparte por los detalles específicos de un objeto concreto. 12 | 13 | 2. **Modularidad**: Al definir una clase, estás agrupando propiedades relacionadas en un solo concepto, lo que ayuda a mantener el código organizado y fácil de entender. Esta modularidad es clave en sistemas complejos, donde diferentes clases pueden interactuar de forma coherente. 14 | 15 | 3. **Reusabilidad**: Una vez creada, una clase puede utilizarse para crear múltiples objetos similares. Este enfoque favorece la reutilización del código y promueve la consistencia dentro de una aplicación. 16 | 17 | 4. **Encapsulamiento**: Aunque este concepto suele relacionarse también con el acceso controlado a los datos, en un sentido básico, el encapsulamiento se refiere a que una clase agrupa las propiedades de un objeto en una sola entidad, ocultando los detalles internos. 18 | 19 | ### ¿Cómo se crea una clase? 20 | 21 | Desde un punto de vista conceptual, crear una clase implica identificar qué características y comportamientos serán comunes en todos los objetos que pertenecerán a esa clase. Este proceso incluye: 22 | 23 | 1. **Identificación de atributos**: Al crear una clase, primero se definen los atributos que todos los objetos de ese tipo compartirán. En la clase "Persona", estos atributos podrían incluir "nombre", "edad", "altura", entre otros. Estos atributos son los rasgos que definen al objeto, y cada instancia tendrá valores específicos para cada uno de ellos. 24 | 25 | 2. **Definición de relaciones**: Una clase también puede relacionarse con otras clases. Por ejemplo, una clase "Coche" podría tener un atributo que se refiera a un objeto de la clase "Motor". Estas relaciones permiten construir estructuras más complejas y realistas. 26 | 27 | 3. **Categorización**: A veces, una clase puede definirse a partir de una categoría más general. Por ejemplo, si tienes una clase "Animal", podrías derivar clases como "Perro" o "Gato" que heredan las características generales de "Animal", pero añaden sus propias propiedades distintivas. Este enfoque jerárquico se llama **herencia**. 28 | 29 | ### ¿Por qué son importantes las clases? 30 | 31 | Las clases son fundamentales en la programación orientada a objetos porque permiten crear modelos del mundo real o de sistemas abstractos con un alto nivel de organización y claridad. Al definir una clase, se establecen las bases para que todos los objetos creados a partir de ella sigan un patrón común, facilitando así la consistencia en el manejo de datos y en las interacciones dentro de un sistema. Además, al trabajar con clases, se promueve la reutilización del código y se facilita la ampliación y mantenimiento del sistema a lo largo del tiempo. 32 | 33 | En conclusión, una clase es la definición teórica de un conjunto de objetos que comparten atributos y potencialmente ciertos comportamientos. Es el plano que permite construir y organizar objetos en un sistema de forma modular, reusando y encapsulando características comunes. Al definir una clase, se sientan las bases para crear objetos que representen tanto entidades del mundo real como conceptos abstractos, permitiendo construir sistemas complejos con mayor orden y eficiencia. -------------------------------------------------------------------------------- /3.Java POO/13.Metodos y como crearlos.md: -------------------------------------------------------------------------------- 1 | # Metodos y como crearlos 2 | 3 | Un **método** es un conjunto de instrucciones que realiza una tarea específica dentro de un programa. Imagina que los métodos son pequeñas "fábricas" dentro de un software: cada fábrica tiene una misión clara, como ensamblar una pieza o empacar un producto. Estas fábricas pueden ser activadas en cualquier momento por el programa para ejecutar su tarea. 4 | 5 | ### ¿Qué son los métodos? 6 | 7 | Los métodos son la manera en la que organizamos las acciones en un programa. Piensa en ellos como recetas: un conjunto de pasos detallados para lograr un resultado. Por ejemplo, una receta de cocina es un método que transforma ingredientes en un plato terminado. Del mismo modo, en programación, un método toma datos (como ingredientes), sigue un conjunto de pasos (instrucciones) y produce un resultado (el plato final). 8 | 9 | ### Principales características de un método: 10 | 11 | 1. **Tarea específica**: Un método tiene una función bien definida. Por ejemplo, un método podría sumar dos números, buscar un dato en una lista, o imprimir un mensaje en pantalla. Esto permite dividir un problema complejo en partes más pequeñas y manejables. 12 | 13 | 2. **Modularidad**: Los métodos son módulos independientes que puedes combinar. Esto te permite reutilizar el código y mantenerlo organizado. 14 | 15 | 3. **Encapsulación de la lógica**: Todo el código relacionado con una acción está dentro del método. Esto evita la dispersión de instrucciones por todo el programa. 16 | 17 | 4. **Entrada de datos (parámetros)**: Algunos métodos necesitan información adicional para funcionar. Por ejemplo, si tienes un método para calcular el área de un rectángulo, este necesitará conocer el largo y el ancho. 18 | 19 | 5. **Salida (valor de retorno)**: Después de realizar su tarea, un método puede devolver un resultado, como el área del rectángulo calculada. Sin embargo, no todos los métodos devuelven un valor; algunos solo realizan acciones. 20 | 21 | ### ¿Cómo se crea un método? 22 | 23 | Crear un método es como diseñar un plan para resolver un problema específico. Aquí se describen los pasos generales, sin depender de un lenguaje de programación en particular: 24 | 25 | 1. **Definir el propósito del método**: Debes preguntarte, ¿qué quiero lograr con este método? Es fundamental tener claro qué problema estás resolviendo. 26 | 27 | 2. **Decidir si necesita parámetros**: Evalúa si el método necesita información para funcionar. En el caso de un método que calcule el área de un rectángulo, necesitarás los parámetros “largo” y “ancho”. 28 | 29 | 3. **Definir los pasos lógicos (cuerpo del método)**: Aquí es donde especificas las instrucciones necesarias para cumplir la tarea. Estos pasos deben estar ordenados y enfocados en la tarea específica. 30 | 31 | 4. **Decidir si devolverá un resultado**: Algunos métodos solo realizan una acción (como mostrar un mensaje) y no necesitan devolver nada. Otros, como el cálculo de un área, deben devolver un valor. 32 | 33 | 5. **Nombrar el método de manera descriptiva**: Dale un nombre que refleje claramente su propósito. Por ejemplo, si tu método suma dos números, podrías llamarlo `sumar`. 34 | 35 | ### Ejemplos teóricos 36 | 37 | Para entender mejor cómo funcionan los métodos, veamos algunos ejemplos cotidianos en la vida real: 38 | 39 | #### Ejemplo 1: Preparar café 40 | 41 | Imagina que tienes un método llamado `prepararCafe`. Este método podría seguir estos pasos: 42 | 43 | - **Nombre del método**: `prepararCafe`. 44 | - **Parámetros**: Tipo de café, cantidad de agua, cantidad de azúcar. 45 | - **Cuerpo del método**: 46 | 1. Hervir agua. 47 | 2. Añadir café según el tipo. 48 | 3. Mezclar con azúcar. 49 | 4. Servir en la taza. 50 | - **Valor de retorno**: Una taza de café lista para beber. 51 | 52 | Este método podría ser invocado cada vez que quieras preparar café. Lo único que cambiarías serían los parámetros, como el tipo de café o la cantidad de azúcar. 53 | 54 | #### Ejemplo 2: Encender una lámpara 55 | 56 | Imagina que tienes un método llamado `encenderLampara`. Este método es sencillo: 57 | 58 | - **Nombre del método**: `encenderLampara`. 59 | - **Parámetros**: Ninguno. 60 | - **Cuerpo del método**: 61 | 1. Verificar si la lámpara está conectada. 62 | 2. Activar el interruptor. 63 | - **Valor de retorno**: Ninguno (solo enciende la lámpara). 64 | 65 | Cada vez que llamas a `encenderLampara`, la lámpara se encenderá si está correctamente conectada. 66 | 67 | #### Ejemplo 3: Comprar en un supermercado 68 | 69 | En este caso, podrías tener un método más complejo llamado `comprarEnSupermercado`: 70 | 71 | - **Nombre del método**: `comprarEnSupermercado`. 72 | - **Parámetros**: Lista de compras, presupuesto. 73 | - **Cuerpo del método**: 74 | 1. Tomar el carrito de compras. 75 | 2. Recorrer los pasillos buscando los productos de la lista. 76 | 3. Revisar precios y compararlos con el presupuesto. 77 | 4. Pagar en la caja. 78 | 5. Guardar las compras en bolsas. 79 | - **Valor de retorno**: Una lista de productos comprados. 80 | 81 | Este método encapsula todo el proceso de hacer compras en el supermercado, desde tomar un carrito hasta pagar en la caja. 82 | 83 | ### Ventajas de los métodos 84 | 85 | 1. **Organización y modularidad**: Los métodos permiten organizar el código de manera estructurada, facilitando su comprensión. 86 | 2. **Reutilización**: Puedes reutilizar los métodos en distintas partes de tu programa sin reescribir el mismo código. 87 | 3. **Mantenimiento**: Si algo debe cambiar en la forma en que se realiza una tarea, solo debes modificar el método, y todas las partes del programa que lo utilizan se verán afectadas. 88 | 89 | En resumen, los métodos son una herramienta esencial en la programación. Al encapsular una acción en un bloque de código bien definido, se logra un software más eficiente, mantenible y fácil de entender. -------------------------------------------------------------------------------- /3.Java POO/14.Métodos Constructores y Objetos En Java.md: -------------------------------------------------------------------------------- 1 | # Métodos, Constructores y Objetos en Java 2 | 3 | En Java, los objetos, constructores y métodos son conceptos fundamentales que permiten a los programadores modelar y manipular datos del mundo real de manera lógica y organizada. 4 | 5 | ### Objetos en Java 6 | 7 | Un **objeto** es una instancia de una clase y representa una entidad con características específicas y comportamientos. En la programación orientada a objetos, un objeto combina datos y métodos para operar sobre esos datos, imitando cómo funcionan las cosas en la vida real. 8 | 9 | - **Estado**: Representado por los atributos (variables) del objeto, los cuales mantienen información relevante. 10 | - **Comportamiento**: Definido por los métodos del objeto, que determinan qué operaciones puede realizar. 11 | 12 | Por ejemplo, en una clase `Coche`, los atributos pueden ser `color`, `marca`, y `velocidad`, y los métodos podrían ser `acelerar()`, `frenar()`, o `mostrarDetalles()`. 13 | 14 | ### Constructores en Java 15 | 16 | Un **constructor** es un método especial que se utiliza para inicializar objetos. Es llamado automáticamente cuando se crea un objeto nuevo usando la palabra clave `new`. Los constructores tienen algunas características distintivas: 17 | 18 | - **Nombre del Constructor**: Siempre debe coincidir con el nombre de la clase. 19 | - **Sin tipo de retorno**: A diferencia de otros métodos, los constructores no tienen tipo de retorno, ni siquiera `void`. 20 | - **Uso principal**: Se utilizan principalmente para inicializar los atributos de un objeto en el momento de su creación. 21 | - **Sobrecarga de Constructores**: Una clase puede tener múltiples constructores con diferentes parámetros, lo que se llama sobrecarga de constructores. Esto permite crear objetos de distintas maneras. 22 | 23 | ### Ejemplos de Constructores y Objetos 24 | 25 | Veamos cómo se aplican estos conceptos con un ejemplo de una clase `Persona`. 26 | 27 | ```java 28 | class Persona { 29 | // Atributos 30 | String nombre; 31 | int edad; 32 | 33 | // Constructor por defecto (sin parámetros) 34 | Persona() { 35 | this.nombre = "Desconocido"; 36 | this.edad = 0; 37 | } 38 | 39 | // Constructor con un parámetro 40 | Persona(String nombre) { 41 | this.nombre = nombre; 42 | this.edad = 0; 43 | } 44 | 45 | // Constructor con dos parámetros 46 | Persona(String nombre, int edad) { 47 | this.nombre = nombre; 48 | this.edad = edad; 49 | } 50 | 51 | // Método para mostrar los detalles de la persona 52 | void mostrarDetalles() { 53 | System.out.println("Nombre: " + nombre); 54 | System.out.println("Edad: " + edad); 55 | } 56 | } 57 | ``` 58 | 59 | #### Creación de Objetos con Constructores 60 | 61 | Ahora, veremos cómo crear objetos `Persona` utilizando los distintos constructores: 62 | 63 | ```java 64 | public class Main { 65 | public static void main(String[] args) { 66 | // Creación de un objeto usando el constructor por defecto 67 | Persona persona1 = new Persona(); 68 | persona1.mostrarDetalles(); // Output: Nombre: Desconocido, Edad: 0 69 | 70 | // Creación de un objeto usando el constructor con un parámetro 71 | Persona persona2 = new Persona("Agustín"); 72 | persona2.mostrarDetalles(); // Output: Nombre: Agustín, Edad: 0 73 | 74 | // Creación de un objeto usando el constructor con dos parámetros 75 | Persona persona3 = new Persona("Beatriz", 25); 76 | persona3.mostrarDetalles(); // Output: Nombre: Beatriz, Edad: 25 77 | } 78 | } 79 | ``` 80 | 81 | ### Importancia de los Constructores 82 | 83 | 1. **Inicialización**: Los constructores permiten inicializar los objetos con valores predeterminados o valores específicos según la necesidad en el momento de su creación. 84 | 2. **Flexibilidad**: Gracias a la sobrecarga, puedes crear objetos con diferentes configuraciones, lo que añade versatilidad al código. 85 | 3. **Encapsulación**: Aunque aquí no tratamos los getters y setters, los constructores también ayudan a proteger los datos al definir cómo deben ser establecidos en el momento de la creación del objeto. 86 | 87 | ### Resumen 88 | 89 | Los **objetos** son las representaciones de entidades del mundo real dentro del código, con estado y comportamiento. Los **constructores** permiten inicializar estos objetos de manera controlada y flexible, haciendo que la programación en Java sea más intuitiva y alineada con la lógica del mundo real. -------------------------------------------------------------------------------- /3.Java POO/15.Getters y Setters en java.md: -------------------------------------------------------------------------------- 1 | # Getters y Setters en Java. 2 | 3 | Los **Getters** y **Setters** son métodos especiales en la programación orientada a objetos que se utilizan para acceder y modificar los valores de los atributos privados de una clase. Aunque no están limitados a un lenguaje en particular, son ampliamente utilizados en Java para seguir el principio de encapsulamiento, uno de los pilares fundamentales de la programación orientada a objetos. 4 | 5 | ### **¿Qué son los Getters y Setters?** 6 | 7 | 1. **Getters** (también llamados "accesores"): Son métodos que permiten leer o recuperar el valor de un atributo privado de una clase. Un Getter no modifica el valor del atributo; simplemente lo devuelve para que pueda ser utilizado por otras partes del programa. 8 | 9 | 2. **Setters** (también llamados "mutadores"): Son métodos que permiten modificar o actualizar el valor de un atributo privado. Los Setters suelen incluir validaciones o reglas de negocio para asegurar que el nuevo valor cumple con ciertos criterios antes de asignarlo al atributo. 10 | 11 | ### **Importancia de los Getters y Setters** 12 | 13 | - **Encapsulamiento**: Al utilizar Getters y Setters, se protege el acceso directo a los atributos de una clase, permitiendo un control más preciso sobre cómo los datos son leídos o modificados. Esto es parte del concepto de encapsulamiento, que ayuda a mantener la integridad y coherencia de los datos. 14 | 15 | - **Validación de Datos**: Los Setters pueden incluir validaciones para asegurar que los valores asignados a los atributos sean válidos. Esto ayuda a evitar que se asignen valores incorrectos o no deseados. 16 | 17 | - **Mantenimiento y Flexibilidad**: Usar Getters y Setters hace que el código sea más fácil de mantener. Si en el futuro se necesita cambiar cómo se calcula un valor o cómo se asigna, solo hay que modificar el Getter o Setter correspondiente, sin necesidad de cambiar el código en otras partes del programa. 18 | 19 | ### **Ejemplo de Getters y Setters en Java** 20 | 21 | Supongamos que tenemos una clase `Persona` con los atributos `nombre` y `edad`. Estos atributos son privados, lo que significa que no pueden ser accedidos directamente desde fuera de la clase. Vamos a usar Getters y Setters para manipular estos atributos. 22 | 23 | ```java 24 | public class Persona { 25 | // Atributos privados 26 | private String nombre; 27 | private int edad; 28 | 29 | // Getter para el atributo 'nombre' 30 | public String getNombre() { 31 | return nombre; // Devuelve el valor del atributo nombre 32 | } 33 | 34 | // Setter para el atributo 'nombre' 35 | public void setNombre(String nombre) { 36 | // Validación opcional: El nombre no debe estar vacío 37 | if (nombre != null && !nombre.isEmpty()) { 38 | this.nombre = nombre; // Asigna el valor si es válido 39 | } else { 40 | System.out.println("El nombre no puede estar vacío."); 41 | } 42 | } 43 | 44 | // Getter para el atributo 'edad' 45 | public int getEdad() { 46 | return edad; // Devuelve el valor del atributo edad 47 | } 48 | 49 | // Setter para el atributo 'edad' 50 | public void setEdad(int edad) { 51 | // Validación opcional: La edad debe ser mayor a 0 52 | if (edad > 0) { 53 | this.edad = edad; // Asigna el valor si es válido 54 | } else { 55 | System.out.println("La edad debe ser mayor a 0."); 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | ### **Uso de Getters y Setters** 62 | 63 | Ahora, veamos cómo se usan los Getters y Setters con un objeto de la clase `Persona`: 64 | 65 | ```java 66 | public class Main { 67 | public static void main(String[] args) { 68 | // Crear un objeto de la clase Persona 69 | Persona persona = new Persona(); 70 | 71 | // Usar el Setter para asignar un valor al nombre 72 | persona.setNombre("Agustín"); 73 | 74 | // Usar el Setter para asignar un valor a la edad 75 | persona.setEdad(25); 76 | 77 | // Usar el Getter para obtener el valor del nombre 78 | System.out.println("Nombre: " + persona.getNombre()); 79 | 80 | // Usar el Getter para obtener el valor de la edad 81 | System.out.println("Edad: " + persona.getEdad()); 82 | } 83 | } 84 | ``` 85 | 86 | ### **Explicación del Ejemplo** 87 | 88 | 1. **Acceso Controlado**: Los atributos `nombre` y `edad` son privados, lo que impide su modificación directa desde fuera de la clase `Persona`. En cambio, se utilizan los métodos `getNombre()` y `getEdad()` para acceder a estos valores, y `setNombre()` y `setEdad()` para modificarlos. 89 | 90 | 2. **Validación de Datos**: En los Setters, hemos añadido condiciones para validar los valores antes de asignarlos. Por ejemplo, el Setter `setNombre()` verifica que el nombre no esté vacío, y `setEdad()` verifica que la edad sea un valor positivo. Esto asegura que los datos dentro de la clase sean siempre coherentes y válidos. 91 | 92 | 3. **Mensajes de Error**: Si se intenta asignar un valor no válido, el Setter imprime un mensaje de error, informando al usuario de la regla que no se ha cumplido. 93 | 94 | Los Getters y Setters son una forma poderosa y esencial de manejar los datos en la programación orientada a objetos, ofreciendo una capa de seguridad y control sobre cómo se interactúa con los atributos de una clase. -------------------------------------------------------------------------------- /3.Java POO/17.Polimorfismo en java.md: -------------------------------------------------------------------------------- 1 | # Polimorfismo en Java 2 | 3 | El polimorfismo es uno de los principios fundamentales de la programación orientada a objetos (POO) que permite a los objetos de diferentes clases ser tratados de manera uniforme a través de una interfaz común. Este concepto ofrece una gran flexibilidad y extensibilidad al software, permitiendo que el mismo código funcione de forma diferente dependiendo del objeto con el que se esté trabajando. Vamos a desglosarlo en más detalle para entender mejor cómo funciona y cuáles son sus beneficios en la programación. 4 | 5 | ### ¿Qué es el Polimorfismo? 6 | 7 | El término "polimorfismo" proviene del griego "poly" (muchos) y "morphos" (formas), lo que literalmente significa "muchas formas". En el contexto de la programación, el polimorfismo se refiere a la capacidad de un objeto para tomar múltiples formas, o más específicamente, a la habilidad de un único método o función para operar con diferentes tipos de datos o clases. 8 | 9 | En Java y otros lenguajes orientados a objetos, el polimorfismo se logra principalmente a través de dos mecanismos: 10 | 1. **Polimorfismo en tiempo de compilación (Sobrecarga de métodos).** 11 | 2. **Polimorfismo en tiempo de ejecución (Sobrescritura de métodos).** 12 | 13 | #### 1. Polimorfismo en Tiempo de Compilación (Sobrecarga de Métodos) 14 | 15 | La sobrecarga de métodos se refiere a la capacidad de definir múltiples métodos con el mismo nombre dentro de la misma clase, pero con diferentes parámetros (diferente número de parámetros o tipos de parámetros). Aunque estos métodos comparten el mismo nombre, el compilador puede distinguir entre ellos en función de la firma del método, es decir, el tipo y la cantidad de argumentos. 16 | 17 | **Ejemplo de sobrecarga de métodos:** 18 | 19 | ```java 20 | public class Calculadora { 21 | 22 | // Método que suma dos números enteros 23 | public int sumar(int a, int b) { 24 | return a + b; 25 | } 26 | 27 | // Sobrecarga del método sumar que suma tres números enteros 28 | public int sumar(int a, int b, int c) { 29 | return a + b + c; 30 | } 31 | 32 | // Sobrecarga del método sumar que suma dos números de tipo double 33 | public double sumar(double a, double b) { 34 | return a + b; 35 | } 36 | } 37 | ``` 38 | 39 | En este ejemplo, el método `sumar` está sobrecargado tres veces. Cada versión del método tiene un conjunto diferente de parámetros, lo que permite que el mismo nombre de método sea utilizado para sumar diferentes cantidades o tipos de números. 40 | 41 | #### 2. Polimorfismo en Tiempo de Ejecución (Sobrescritura de Métodos) 42 | 43 | El polimorfismo en tiempo de ejecución, también conocido como sobrescritura de métodos, ocurre cuando una clase derivada proporciona una implementación específica de un método que ya está definido en su clase base. Este tipo de polimorfismo se basa en la herencia y la capacidad de una clase hija de redefinir un comportamiento de la clase padre. 44 | 45 | **Ejemplo de sobrescritura de métodos:** 46 | 47 | ```java 48 | class Animal { 49 | public void hacerSonido() { 50 | System.out.println("El animal hace un sonido"); 51 | } 52 | } 53 | 54 | class Perro extends Animal { 55 | @Override 56 | public void hacerSonido() { 57 | System.out.println("El perro ladra"); 58 | } 59 | } 60 | 61 | class Gato extends Animal { 62 | @Override 63 | public void hacerSonido() { 64 | System.out.println("El gato maúlla"); 65 | } 66 | } 67 | ``` 68 | 69 | En este ejemplo, tanto la clase `Perro` como la clase `Gato` sobrescriben el método `hacerSonido` de la clase base `Animal`. A través del polimorfismo, se puede invocar el método `hacerSonido` en una instancia de `Animal`, y el comportamiento adecuado se determinará en tiempo de ejecución, dependiendo del tipo real del objeto. 70 | 71 | ### Ventajas del Polimorfismo 72 | 73 | 1. **Flexibilidad y Extensibilidad del Código:** 74 | El polimorfismo permite escribir código más flexible y extensible. Por ejemplo, si en el futuro se agregan nuevas clases como `Pájaro` o `Caballo` que también extienden `Animal`, no sería necesario cambiar el código que utiliza la clase `Animal`, ya que estos nuevos tipos heredan el comportamiento común y pueden redefinir métodos según sea necesario. 75 | 76 | 2. **Reutilización de Código:** 77 | Facilita la reutilización del código al permitir que las funciones trabajen con objetos de clases relacionadas, sin necesidad de modificar la función cada vez que se agrega un nuevo tipo de objeto. 78 | 79 | 3. **Mantenimiento Simplificado:** 80 | Al centralizar la lógica en una clase base y permitir que las clases derivadas implementen sus propias versiones de los métodos, se simplifica el mantenimiento del código. Si se necesita cambiar un comportamiento común, se puede hacer en la clase base y todas las clases derivadas se verán afectadas. 81 | 82 | 4. **Desacoplamiento:** 83 | Permite escribir código desacoplado, donde las dependencias entre clases son mínimas. Esto hace que el sistema sea más fácil de mantener y escalar, ya que los cambios en una clase no afectan a otras clases. 84 | 85 | ### Ejemplo de Polimorfismo en Uso 86 | 87 | Supongamos que tenemos un método que imprime los sonidos de diferentes animales: 88 | 89 | ```java 90 | public void imprimirSonido(Animal animal) { 91 | animal.hacerSonido(); 92 | } 93 | ``` 94 | 95 | Gracias al polimorfismo, podemos pasar cualquier objeto que sea una instancia de `Animal` (incluidos `Perro` y `Gato`) al método `imprimirSonido`, y el comportamiento adecuado se ejecutará en tiempo de ejecución: 96 | 97 | ```java 98 | Animal perro = new Perro(); 99 | Animal gato = new Gato(); 100 | 101 | imprimirSonido(perro); // Imprime "El perro ladra" 102 | imprimirSonido(gato); // Imprime "El gato maúlla" 103 | ``` 104 | 105 | ### Conclusión 106 | 107 | El polimorfismo es un concepto esencial en la programación orientada a objetos, que proporciona una forma de manejar objetos de diferentes tipos de manera uniforme. A través de la herencia y la sobrescritura de métodos, permite a los desarrolladores escribir código más flexible, extensible y fácil de mantener, mejorando la calidad del software y facilitando su evolución a lo largo del tiempo. -------------------------------------------------------------------------------- /3.Java POO/18.Encapsulamiento en Java.md: -------------------------------------------------------------------------------- 1 | # Encapsulamiento en la Programación Orientada a Objetos (POO) 2 | 3 | El encapsulamiento es uno de los cuatro pilares fundamentales de la Programación Orientada a Objetos (POO), junto con la herencia, el polimorfismo y la abstracción. Esta característica permite agrupar datos y métodos que operan sobre esos datos en una sola entidad o "clase", ocultando su implementación interna y proporcionando un acceso controlado a ellos. 4 | 5 | ### ¿Qué es el Encapsulamiento? 6 | 7 | El encapsulamiento se refiere a la práctica de restringir el acceso directo a algunos de los componentes de un objeto y solo permitir la modificación de los mismos a través de métodos definidos. En otras palabras, los atributos (o variables de instancia) de una clase no deben ser accesibles directamente desde fuera de la clase; en cambio, deben ser privados y solo manipulables mediante métodos públicos, que actúan como una interfaz para el usuario. 8 | 9 | Por ejemplo, supongamos que tienes una clase `CuentaBancaria` con un atributo `saldo`. No sería adecuado permitir que cualquier parte del código pueda modificar este saldo directamente, ya que esto podría causar errores o comportamientos inesperados. En su lugar, usarías métodos como `depositar(double cantidad)` o `retirar(double cantidad)` para manipular el saldo, asegurando así que cualquier cambio cumpla con las reglas de negocio definidas. 10 | 11 | ### Beneficios del Encapsulamiento 12 | 13 | 1. **Ocultación de Datos**: El encapsulamiento oculta los detalles internos de la clase y protege los datos de acceso no autorizado o cambios no controlados. Los datos sensibles no son directamente accesibles desde el exterior de la clase, lo que evita la corrupción o uso indebido de los mismos. 14 | 15 | 2. **Control de Modificación**: A través de métodos específicos, puedes controlar cómo los datos de la clase son accedidos o modificados. Por ejemplo, puedes verificar que un valor esté dentro de un rango válido antes de permitir que se actualice un atributo. 16 | 17 | 3. **Mantenibilidad**: Facilita el mantenimiento del código. Si los detalles internos de la clase necesitan cambiar (por ejemplo, la estructura de los datos o el algoritmo utilizado), estos cambios no afectarán a las partes del código que interactúan con la clase, siempre que la interfaz pública (los métodos) permanezca igual. 18 | 19 | 4. **Reutilización del Código**: Al encapsular el comportamiento de una clase, puedes reutilizarla sin preocuparte por cómo se implementan los detalles internos. Solo necesitas conocer la interfaz pública de la clase. 20 | 21 | 5. **Flexibilidad y Extensibilidad**: Permite modificar la implementación interna de la clase sin cambiar su interfaz pública. Esto significa que puedes mejorar o optimizar el código sin afectar a otros componentes que utilizan la clase. 22 | 23 | ### Modificadores de Acceso en Java 24 | 25 | En Java, el encapsulamiento se logra principalmente mediante el uso de **modificadores de acceso** que controlan la visibilidad y accesibilidad de las clases, atributos, métodos y constructores. Los modificadores de acceso son: 26 | 27 | 1. **Public**: El acceso más abierto. Los miembros (atributos, métodos, constructores) declarados como públicos (`public`) son accesibles desde cualquier clase, sin importar el paquete al que pertenezcan. Utilizar `public` significa que no hay restricciones para acceder al miembro. 28 | 29 | 2. **Protected**: Los miembros declarados como `protected` son accesibles solo dentro del mismo paquete y por clases hijas (subclases) que heredan de la clase donde se define el miembro. Este modificador permite cierto grado de encapsulamiento, permitiendo el acceso solo en contextos controlados. 30 | 31 | 3. **Private**: El modificador de acceso más restrictivo. Los miembros declarados como `private` solo son accesibles dentro de la misma clase donde se definen. No pueden ser accedidos desde ninguna otra clase, ni siquiera desde subclases. Esto garantiza el máximo nivel de encapsulamiento. 32 | 33 | 4. **Default (sin modificador)**: Si no se especifica ningún modificador de acceso, se considera acceso por defecto o de paquete. Los miembros con acceso por defecto son accesibles solo dentro del mismo paquete. No pueden ser accedidos desde clases en paquetes diferentes, lo cual proporciona un nivel de encapsulamiento intermedio. 34 | 35 | ### Ejemplo de Encapsulamiento 36 | 37 | Para ilustrar el encapsulamiento, consideremos un ejemplo de una clase `Persona` en Java: 38 | 39 | ```java 40 | public class Persona { 41 | // Atributos privados (encapsulados) 42 | private String nombre; 43 | private int edad; 44 | 45 | // Constructor de la clase 46 | public Persona(String nombre, int edad) { 47 | this.nombre = nombre; 48 | this.edad = edad; 49 | } 50 | 51 | // Método Getter para obtener el nombre 52 | public String getNombre() { 53 | return nombre; 54 | } 55 | 56 | // Método Setter para establecer el nombre 57 | public void setNombre(String nombre) { 58 | this.nombre = nombre; 59 | } 60 | 61 | // Método Getter para obtener la edad 62 | public int getEdad() { 63 | return edad; 64 | } 65 | 66 | // Método Setter para establecer la edad 67 | public void setEdad(int edad) { 68 | if (edad > 0) { // Validación de entrada 69 | this.edad = edad; 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | En este ejemplo: 76 | 77 | - Los atributos `nombre` y `edad` están declarados como `private`, por lo que no pueden ser accedidos directamente desde fuera de la clase `Persona`. 78 | - Los métodos `getNombre()` y `getEdad()` son **Getters** que permiten leer los valores de los atributos privados. 79 | - Los métodos `setNombre(String nombre)` y `setEdad(int edad)` son **Setters** que permiten modificar los valores de los atributos privados. Estos métodos pueden incluir lógica adicional, como la validación de los valores de entrada. 80 | 81 | ### Resumen 82 | 83 | El encapsulamiento es esencial para crear software robusto, seguro y fácil de mantener. Este concepto permite a los desarrolladores proteger los datos y definir claramente cómo pueden ser manipulados, garantizando que cualquier modificación siga las reglas de negocio establecidas y reduciendo la posibilidad de errores. Utilizando modificadores de acceso como `private`, `protected` y `public`, se puede controlar con precisión quién puede ver o modificar cada componente de una clase, lo que resulta en aplicaciones más organizadas, modulares y seguras. -------------------------------------------------------------------------------- /3.Java POO/19.Clases Abstractas.md: -------------------------------------------------------------------------------- 1 | # Clases Abstractas en Programación Orientada a Objetos 2 | 3 | En el contexto de la programación orientada a objetos (POO), las **clases abstractas** son herramientas poderosas y fundamentales para diseñar estructuras de software flexibles y mantenibles. A pesar de que a menudo se consideran un tema complejo, las clases abstractas son, en realidad, bastante sencillas de entender si las abordamos paso a paso. 4 | 5 | #### ¿Qué es una Clase Abstracta? 6 | 7 | Una **clase abstracta** es una clase que no se puede instanciar directamente, lo que significa que no podemos crear objetos de esa clase específica. Esta restricción se debe a que la clase abstracta está destinada a servir como una base o plantilla para otras clases relacionadas. En otras palabras, actúa como una guía general a partir de la cual se pueden construir clases más específicas. 8 | 9 | Una clase abstracta se declara utilizando la palabra clave `abstract` en su definición, y puede contener tanto **métodos abstractos** como métodos concretos. 10 | 11 | - **Métodos abstractos**: Son métodos que solo están declarados en la clase abstracta, pero no tienen implementación. Se definen con su firma (nombre del método, tipo de retorno, y parámetros) y se terminan con un punto y coma `;`. Las subclases que heredan de esta clase abstracta deben proporcionar una implementación concreta para estos métodos. 12 | 13 | - **Métodos concretos**: Son métodos que tienen una implementación completa dentro de la clase abstracta. Las subclases pueden usar estos métodos tal como están o, en algunos casos, sobreescribirlos si es necesario. 14 | 15 | #### ¿Para Qué se Utilizan las Clases Abstractas? 16 | 17 | Las clases abstractas se utilizan para crear una **abstracción general** que define un comportamiento o estructura común para todas sus subclases, sin preocuparse de los detalles específicos de implementación de esas subclases. Esto promueve la **reutilización del código** y ayuda a crear una jerarquía de clases más estructurada. 18 | 19 | Al usar clases abstractas, puedes: 20 | 21 | 1. **Definir un contrato o una plantilla**: Obligar a todas las subclases a implementar ciertos métodos que son esenciales para su funcionamiento. Esto es útil cuando diferentes subclases deben compartir el mismo conjunto de métodos, pero cada una debe proporcionar su propia implementación. 22 | 23 | 2. **Reutilizar código**: Permitir que las subclases hereden métodos y propiedades comunes de la clase abstracta, reduciendo la duplicación de código y haciendo que el mantenimiento del código sea más eficiente. 24 | 25 | 3. **Crear una base común**: Ofrecer una estructura básica que pueda ser extendida por otras clases, facilitando la gestión de proyectos más grandes y complejos. 26 | 27 | #### Ejemplo de Clase Abstracta en Java 28 | 29 | Imaginemos un escenario donde estamos desarrollando una aplicación de zoológico. Queremos definir una clase general para diferentes tipos de animales, pero cada animal tiene su propio comportamiento único. 30 | 31 | ```java 32 | abstract class Animal { 33 | // Método abstracto: no tiene implementación 34 | abstract void hacerSonido(); 35 | 36 | // Método concreto: tiene implementación 37 | void dormir() { 38 | System.out.println("El animal está durmiendo."); 39 | } 40 | } 41 | ``` 42 | 43 | En este ejemplo, `Animal` es una clase abstracta que contiene un método abstracto `hacerSonido()` y un método concreto `dormir()`. Todas las subclases que hereden de `Animal` deberán implementar el método `hacerSonido()`. 44 | 45 | Ahora, definimos algunas subclases: 46 | 47 | ```java 48 | class Perro extends Animal { 49 | @Override 50 | void hacerSonido() { 51 | System.out.println("El perro ladra: ¡Guau, guau!"); 52 | } 53 | } 54 | 55 | class Gato extends Animal { 56 | @Override 57 | void hacerSonido() { 58 | System.out.println("El gato maúlla: ¡Miau, miau!"); 59 | } 60 | } 61 | ``` 62 | 63 | En este caso, `Perro` y `Gato` son subclases de `Animal`. Cada una de ellas proporciona su propia implementación del método `hacerSonido()`, pero pueden usar el método `dormir()` de la clase abstracta `Animal` sin necesidad de redefinirlo. 64 | 65 | #### Ventajas de Utilizar Clases Abstractas 66 | 67 | 1. **Facilita el mantenimiento del código**: Al tener una estructura común y una serie de métodos que todas las subclases deben implementar, el código es más fácil de entender y mantener. 68 | 69 | 2. **Promueve la reutilización de código**: Las subclases pueden heredar métodos ya implementados en la clase abstracta, reduciendo la necesidad de escribir código redundante. 70 | 71 | 3. **Permite la consistencia**: Garantiza que todas las subclases cumplan con ciertos contratos o comportamientos definidos en la clase abstracta. 72 | 73 | #### Limitaciones de las Clases Abstractas 74 | 75 | - **Herencia simple**: En Java, una clase solo puede heredar de una única clase abstracta, lo que limita la capacidad de mezclar y combinar comportamientos de múltiples fuentes. 76 | 77 | - **No se puede instanciar**: No puedes crear directamente un objeto de una clase abstracta; siempre necesitas una subclase concreta que implemente todos los métodos abstractos. 78 | 79 | ### Conclusión 80 | 81 | Las clases abstractas son una herramienta fundamental en POO para definir estructuras de software flexibles y mantener un código limpio y reutilizable. Aunque pueden parecer complicadas al principio, una vez que comprendes su propósito y cómo se usan, se convierten en una parte esencial del diseño de software robusto y mantenible. -------------------------------------------------------------------------------- /3.Java POO/20.Interfaces en Java.md: -------------------------------------------------------------------------------- 1 | # Interfaces en Java. 2 | 3 | Las interfaces en programación orientada a objetos (POO) son un concepto fundamental que permite definir un contrato o conjunto de reglas que una clase debe seguir. A diferencia de las clases, que pueden contener tanto atributos como métodos con implementación concreta, una interfaz únicamente define métodos abstractos (es decir, métodos sin implementación) y puede contener constantes, pero no variables de instancia. 4 | 5 | ### ¿Qué es una Interfaz? 6 | 7 | Una **interfaz** se puede considerar como una especificación de métodos que una clase puede implementar. No proporciona detalles sobre cómo deben funcionar esos métodos; simplemente establece qué métodos deben existir. Este concepto es crucial para promover la **desacoplar** o separar los componentes del software, lo que permite una mayor flexibilidad, extensibilidad y reutilización de código. 8 | 9 | Por ejemplo, si tienes una interfaz llamada `Volador`, puede definir métodos como `volar()` y `aterrizar()`. Cualquier clase que implemente la interfaz `Volador` se verá obligada a proporcionar una implementación concreta de esos métodos. Esto garantiza que cualquier objeto que sea de tipo `Volador` pueda ser tratado uniformemente, independientemente de los detalles de implementación específicos. 10 | 11 | ### Características Claves de las Interfaces 12 | 13 | 1. **Colección de Métodos Abstractos**: Las interfaces solo pueden contener métodos abstractos, lo que significa que los métodos no tienen implementación (cuerpo de método). Las clases que implementan la interfaz son responsables de proporcionar la implementación concreta de estos métodos. 14 | 15 | 2. **Constantes**: Los atributos dentro de una interfaz son siempre constantes, es decir, deben ser `public static final`. No es común que las interfaces contengan atributos, pero si los tienen, no pueden ser modificados después de su definición. 16 | 17 | 3. **Herencia Múltiple**: Una de las principales ventajas de las interfaces es que permiten a las clases implementar múltiples interfaces. Esto es conocido como **herencia múltiple**. En lenguajes como Java, donde una clase no puede heredar de más de una clase, las interfaces proporcionan una forma de implementar múltiples comportamientos. 18 | 19 | 4. **Acceso Público por Defecto**: Todos los métodos dentro de una interfaz son implícitamente `public` y abstractos. No se puede usar otros modificadores de acceso como `protected` o `private` para los métodos de una interfaz. 20 | 21 | 5. **Flexibilidad y Polimorfismo**: Las interfaces permiten utilizar el polimorfismo de una manera poderosa. Un mismo objeto puede ser tratado como instancia de múltiples tipos (interfaces) que implementa, lo que permite escribir código más general y flexible. 22 | 23 | ### ¿Por Qué Usar Interfaces? 24 | 25 | Las interfaces se utilizan para: 26 | 27 | 1. **Definir Contratos Comunes**: Permiten definir un conjunto común de métodos que diferentes clases pueden implementar de diversas maneras. Esto facilita la integración de sistemas y la sustitución de componentes. 28 | 29 | 2. **Lograr Abstracción Completa**: A diferencia de las clases abstractas, que pueden contener tanto métodos abstractos como métodos concretos, las interfaces solo pueden contener métodos abstractos, proporcionando una abstracción completa. 30 | 31 | 3. **Fomentar la Desacoplamiento**: Al utilizar interfaces, se reduce la dependencia directa de una clase específica, lo que hace que el sistema sea más flexible, modular y fácil de mantener. 32 | 33 | 4. **Facilitar la Herencia Múltiple de Comportamientos**: Como ya se mencionó, las interfaces permiten que una clase implemente múltiples tipos de comportamiento sin las limitaciones de herencia simple que existe en muchos lenguajes. 34 | 35 | ### Ejemplo de Uso de Interfaces en Java 36 | 37 | Para ilustrar cómo funcionan las interfaces, consideremos el siguiente ejemplo: 38 | 39 | ```java 40 | // Definición de la interfaz Volador 41 | public interface Volador { 42 | void volar(); 43 | void aterrizar(); 44 | } 45 | 46 | // Implementación de la interfaz en la clase Avion 47 | public class Avion implements Volador { 48 | @Override 49 | public void volar() { 50 | System.out.println("El avión está volando."); 51 | } 52 | 53 | @Override 54 | public void aterrizar() { 55 | System.out.println("El avión ha aterrizado."); 56 | } 57 | } 58 | 59 | // Implementación de la interfaz en la clase Pajaro 60 | public class Pajaro implements Volador { 61 | @Override 62 | public void volar() { 63 | System.out.println("El pájaro está volando."); 64 | } 65 | 66 | @Override 67 | public void aterrizar() { 68 | System.out.println("El pájaro ha aterrizado."); 69 | } 70 | } 71 | ``` 72 | 73 | En este ejemplo: 74 | 75 | - La interfaz `Volador` define dos métodos: `volar()` y `aterrizar()`. 76 | - Tanto la clase `Avion` como `Pajaro` implementan la interfaz `Volador`, por lo tanto, ambas clases deben proporcionar una implementación concreta para estos métodos. 77 | - Ahora, cualquier instancia de `Avion` o `Pajaro` puede ser tratada como un objeto de tipo `Volador`, permitiendo una gran flexibilidad y polimorfismo. 78 | 79 | ### Diferencia entre Clases Abstractas e Interfaces 80 | 81 | Aunque tanto las clases abstractas como las interfaces permiten definir métodos que deben ser implementados por las clases hijas, existen diferencias importantes entre ellas: 82 | 83 | 1. **Métodos con Implementación**: Las clases abstractas pueden contener métodos concretos con implementación, mientras que las interfaces solo pueden tener métodos abstractos hasta Java 8, donde se introdujeron los métodos predeterminados (`default`) con implementación. 84 | 85 | 2. **Atributos**: Las clases abstractas pueden tener atributos no constantes, mientras que las interfaces solo pueden contener atributos que son constantes (`public static final`). 86 | 87 | 3. **Herencia**: Una clase puede heredar de una única clase abstracta, pero puede implementar múltiples interfaces. 88 | 89 | ### Conclusión 90 | 91 | Las interfaces son esenciales para definir contratos entre las diferentes partes de un software. Permiten a las clases tener un comportamiento común, independientemente de su implementación concreta, facilitando la integración, el mantenimiento y la evolución del sistema. Utilizar interfaces en conjunto con otros principios de POO, como herencia, polimorfismo y encapsulamiento, resulta en código más limpio, reutilizable y extensible. -------------------------------------------------------------------------------- /3.Java POO/22.ArrayList en Java.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es un ArrayList en Java? 2 | 3 | Un `ArrayList` en Java es una clase que forma parte del paquete `java.util` y representa una estructura de datos que permite almacenar y manipular elementos de manera dinámica. A diferencia de los arrays tradicionales, cuyo tamaño es fijo una vez definido, un `ArrayList` puede crecer y reducirse automáticamente conforme se añaden o eliminan elementos, ofreciendo mayor flexibilidad para gestionar colecciones de datos. 4 | 5 | #### Características de un `ArrayList` 6 | 7 | 1. **Matriz Dinámica**: Un `ArrayList` se comporta como una matriz dinámica que puede cambiar de tamaño en tiempo de ejecución. Esto significa que cuando se añade un nuevo elemento y no hay suficiente espacio en la matriz interna, se crea una nueva matriz más grande y se copian todos los elementos existentes. 8 | 9 | 2. **Herencia y Implementación**: 10 | - `ArrayList` hereda de la clase abstracta `AbstractList`, lo que proporciona una base de métodos para gestionar listas de manera general. 11 | - Implementa la interfaz `List`, lo que significa que el `ArrayList` debe cumplir con el contrato de esta interfaz, proporcionando métodos como `add()`, `remove()`, `get()`, `set()`, entre otros. 12 | 13 | 3. **Permite Elementos Duplicados**: En un `ArrayList` es posible almacenar elementos duplicados. Esto significa que se pueden tener múltiples elementos con el mismo valor o referencia en diferentes posiciones de la lista. 14 | 15 | 4. **Orden de Inserción**: Los elementos en un `ArrayList` se almacenan en el orden en el que fueron añadidos. Esto permite mantener un registro ordenado de los elementos según su orden de inserción. 16 | 17 | 5. **Acceso Aleatorio**: Una de las grandes ventajas de un `ArrayList` es su capacidad de acceder rápidamente a los elementos mediante su índice. Por ejemplo, si se desea acceder al tercer elemento de la lista, se puede hacer directamente usando `arrayList.get(2)` (recordando que los índices en Java comienzan en 0). 18 | 19 | 6. **Manipulación Relativamente Lenta**: Aunque el `ArrayList` permite el acceso rápido a los elementos a través de su índice, la manipulación de los elementos puede ser relativamente lenta en comparación con otras estructuras de datos como las `LinkedLists`. Esto se debe a que las operaciones que implican agregar o eliminar elementos en el medio de la lista requieren mover todos los elementos subsiguientes para mantener el orden correcto. 20 | 21 | #### Ventajas del `ArrayList` 22 | 23 | - **Flexibilidad de Tamaño**: Su capacidad para crecer o reducirse dinámicamente hace que el `ArrayList` sea ideal para aplicaciones donde el número de elementos no es conocido de antemano o puede cambiar con frecuencia. 24 | 25 | - **Acceso Rápido a Elementos**: Gracias a su implementación basada en matrices, proporciona un acceso rápido a los elementos por índice, siendo eficiente para operaciones de búsqueda y recuperación de elementos. 26 | 27 | - **Fácil de Usar**: La clase `ArrayList` proporciona una serie de métodos útiles que facilitan la gestión de colecciones de elementos, como `add()`, `remove()`, `contains()`, entre otros. 28 | 29 | #### Desventajas del `ArrayList` 30 | 31 | - **Costos de Manipulación**: Si se necesitan muchas inserciones o eliminaciones en el medio de la lista, el rendimiento puede verse afectado, ya que los elementos deben ser desplazados para mantener el orden de inserción. Esto puede volverse costoso en términos de tiempo cuando la lista es muy grande. 32 | 33 | - **Consumo de Memoria**: Aunque el `ArrayList` maneja automáticamente su tamaño, cada vez que necesita crecer más allá de su capacidad actual, crea un nuevo array con mayor tamaño y copia los elementos existentes. Este proceso puede ser costoso en términos de memoria y tiempo si se realizan muchas operaciones de adición o eliminación. 34 | 35 | #### Ejemplo de Uso de un `ArrayList` 36 | 37 | A continuación, se presenta un ejemplo básico de cómo se utiliza un `ArrayList` en Java: 38 | 39 | ```java 40 | import java.util.ArrayList; 41 | 42 | public class EjemploArrayList { 43 | public static void main(String[] args) { 44 | // Crear un ArrayList de String 45 | ArrayList nombres = new ArrayList<>(); 46 | 47 | // Agregar elementos al ArrayList 48 | nombres.add("Juan"); 49 | nombres.add("Ana"); 50 | nombres.add("Carlos"); 51 | 52 | // Mostrar los elementos del ArrayList 53 | System.out.println("Elementos en la lista: " + nombres); 54 | 55 | // Acceder a un elemento por su índice 56 | String primerNombre = nombres.get(0); 57 | System.out.println("Primer nombre en la lista: " + primerNombre); 58 | 59 | // Modificar un elemento en una posición específica 60 | nombres.set(1, "María"); 61 | System.out.println("Lista después de la modificación: " + nombres); 62 | 63 | // Eliminar un elemento por índice 64 | nombres.remove(2); 65 | System.out.println("Lista después de la eliminación: " + nombres); 66 | } 67 | } 68 | ``` 69 | 70 | #### Diferencias entre `ArrayList` y otras Listas 71 | 72 | - **`LinkedList`**: Aunque también implementa la interfaz `List`, `LinkedList` es más eficiente en términos de inserciones y eliminaciones en el medio de la lista, ya que está basada en nodos enlazados. Sin embargo, tiene un acceso más lento a los elementos individuales en comparación con `ArrayList`. 73 | 74 | - **`Stack`**: Es una subclase de `Vector` que sigue el principio de "Last In, First Out" (LIFO). Aunque también es una lista, está diseñada específicamente para operaciones de pila (push y pop). 75 | 76 | En resumen, un `ArrayList` es una herramienta poderosa y flexible para trabajar con colecciones de datos en Java, especialmente cuando se requiere acceso rápido por índice y la capacidad de gestionar un número variable de elementos. Sin embargo, es importante tener en cuenta sus características y limitaciones para decidir cuándo es la mejor opción en comparación con otras implementaciones de listas. -------------------------------------------------------------------------------- /3.Java POO/24.Diferencias entre ArrayLists y LinkedLists.md: -------------------------------------------------------------------------------- 1 | # Diferencias entre ArrayLists y LinkedLists en Java: Una Comparación Exhaustiva 2 | 3 | En Java, tanto `ArrayList` como `LinkedList` son implementaciones de la interfaz `List` de la API de colecciones. Ambas clases proporcionan una manera de almacenar una secuencia de elementos, pero difieren significativamente en cómo gestionan la memoria, cómo realizan operaciones de inserción y eliminación, y en sus características de rendimiento para diferentes tipos de operaciones. A continuación, te explico en detalle las principales diferencias entre `ArrayList` y `LinkedList`, y cuándo es más adecuado usar una u otra. 4 | 5 | ### 1. **Estructura Interna de Datos** 6 | 7 | - **ArrayList**: Utiliza un **arreglo dinámico** como estructura subyacente para almacenar los elementos. Esto significa que los elementos están almacenados de manera **contigua** en la memoria. Cuando se agrega un elemento a un `ArrayList`, y el arreglo subyacente está lleno, se crea un nuevo arreglo de mayor tamaño y se copian todos los elementos del viejo al nuevo. Esta operación de copia puede ser costosa en términos de tiempo. 8 | 9 | - **LinkedList**: Utiliza una **lista doblemente enlazada**. Cada elemento de una `LinkedList` es un nodo que contiene una referencia al nodo siguiente y al nodo anterior en la lista. Los elementos no están almacenados contiguamente en memoria, sino que cada nodo puede estar en cualquier parte de la memoria, conectado a su vecino mediante referencias. 10 | 11 | ### 2. **Acceso a Elementos** 12 | 13 | - **ArrayList**: Permite **acceso rápido** a los elementos mediante el uso de índices (`get(int index)` o `set(int index, E element)`), ya que se basa en un arreglo. Acceder a un elemento específico es una operación de **O(1)**, lo que significa que el tiempo de acceso no depende del tamaño de la lista. 14 | 15 | - **LinkedList**: El acceso a los elementos es más **lento** porque, para encontrar un elemento específico, se necesita recorrer los nodos uno por uno desde el inicio o el final de la lista. Este es un proceso de **O(n)**, donde "n" es el número de elementos en la lista, ya que se debe iterar sobre los nodos hasta llegar al índice deseado. 16 | 17 | ### 3. **Inserción y Eliminación de Elementos** 18 | 19 | - **ArrayList**: Las operaciones de **inserción y eliminación** son más costosas en términos de rendimiento cuando se realizan en el medio de la lista. Esto se debe a que, después de insertar o eliminar un elemento, todos los elementos subsiguientes deben ser desplazados para llenar el vacío o hacer espacio, lo que tiene una complejidad de **O(n)**. 20 | 21 | - **LinkedList**: La **inserción y eliminación** de elementos son operaciones más eficientes en comparación con `ArrayList`, especialmente cuando se trata de elementos en posiciones intermedias o al principio de la lista. Solo es necesario ajustar las referencias de los nodos adyacentes, lo que resulta en una complejidad de **O(1)** para las operaciones en los extremos (inicio o final) y **O(n)** en posiciones intermedias (debido al tiempo necesario para llegar a esa posición). 22 | 23 | ### 4. **Uso de Memoria** 24 | 25 | - **ArrayList**: Es más **eficiente en memoria** para almacenar datos simples porque solo necesita el espacio necesario para los elementos más el tamaño de crecimiento del arreglo subyacente. Sin embargo, como el arreglo puede tener más capacidad que el número de elementos actuales, puede desperdiciar memoria si la lista no está llena. 26 | 27 | - **LinkedList**: Consume **más memoria** porque, además de los datos del elemento, cada nodo necesita almacenar referencias al siguiente y al anterior nodo. Esta sobrecarga de memoria es mayor en comparación con `ArrayList`. 28 | 29 | ### 5. **Iteración y Búsqueda** 30 | 31 | - **ArrayList**: Proporciona una **mejor eficiencia** para la iteración y búsqueda de elementos gracias a su acceso directo basado en índices. Es ideal cuando se requiere un acceso secuencial rápido o cuando se usan bucles para recorrer los elementos de la lista. 32 | 33 | - **LinkedList**: Aunque soporta la iteración, su rendimiento es inferior en comparación con `ArrayList`, especialmente en listas grandes, debido al acceso secuencial necesario para llegar a cada nodo. 34 | 35 | ### 6. **Reubicación en Memoria** 36 | 37 | - **ArrayList**: Dado que utiliza un arreglo interno, necesita **espacio contiguo** en la memoria. Esto puede ser un problema si el tamaño del arreglo crece significativamente, ya que puede llevar a una operación costosa de copia cuando se redimensiona. 38 | 39 | - **LinkedList**: No requiere que los elementos estén contiguamente almacenados, lo que significa que es **más flexible en el uso de memoria**. La inserción o eliminación no requiere un espacio contiguo en memoria. 40 | 41 | ### 7. **Escenarios de Uso Común** 42 | 43 | - **Cuando usar `ArrayList`**: 44 | - Necesitas acceso rápido y frecuente a los elementos mediante índices. 45 | - Las operaciones de inserción y eliminación no son frecuentes o se realizan principalmente al final de la lista. 46 | - Se requiere un almacenamiento más eficiente en términos de memoria. 47 | 48 | - **Cuando usar `LinkedList`**: 49 | - La inserción y eliminación de elementos son operaciones frecuentes, especialmente en posiciones intermedias o al principio de la lista. 50 | - No se necesita un acceso rápido mediante índices. 51 | - Se trabaja con grandes cantidades de datos que cambian de manera dinámica y no se desea el costo de redimensionar los arreglos. 52 | 53 | ### 8. **Consideraciones Finales** 54 | 55 | La elección entre `ArrayList` y `LinkedList` depende en gran medida del tipo de operaciones que se realizarán con mayor frecuencia en tu programa. Si el acceso rápido a elementos específicos es una prioridad y las inserciones/eliminaciones son poco frecuentes, `ArrayList` es la opción ideal. Por otro lado, si se prevé que las inserciones y eliminaciones en posiciones arbitrarias de la lista serán comunes, `LinkedList` puede ofrecer un rendimiento superior. 56 | 57 | **Conclusión**: Ambas implementaciones tienen sus propias ventajas y desventajas. Comprender cómo funcionan internamente y cómo manejan las operaciones puede ayudarte a tomar la mejor decisión en función de los requisitos específicos de tu aplicación. -------------------------------------------------------------------------------- /3.Java POO/25.Stacks en java.md: -------------------------------------------------------------------------------- 1 | # ¿Qué es una Stack (Pila) en Java? 2 | 3 | En Java, una **stack** o **pila** es una estructura de datos fundamental que sigue el principio de **LIFO** (Last-In, First-Out), lo que significa que el último elemento que se añade a la pila será el primero en ser retirado. Este comportamiento es similar a una pila de libros: el último libro colocado en la parte superior es el primero que se puede quitar. 4 | 5 | Las pilas se utilizan en numerosos algoritmos y aplicaciones, como la navegación de páginas web (donde puedes "volver atrás" a la página anterior), el procesamiento de expresiones matemáticas, la evaluación de expresiones en lenguajes de programación y el manejo de llamadas a funciones. 6 | 7 | ### Funcionalidad de la Clase Stack en Java 8 | 9 | Java proporciona una clase integrada llamada `Stack` dentro del paquete `java.util` para implementar pilas. Esta clase hereda de la clase `Vector` y ofrece un conjunto de métodos para operar sobre la pila, como añadir, eliminar, buscar y revisar elementos. 10 | 11 | #### Métodos Clave de la Clase Stack 12 | 13 | 1. **`push(E item)`**: 14 | Este método se utiliza para añadir un elemento al tope de la pila. La complejidad de esta operación es constante **O(1)**, ya que solo implica colocar el elemento en el último índice disponible de la pila. 15 | ```java 16 | Stack stack = new Stack<>(); 17 | stack.push(10); // Añade el número 10 al tope de la pila 18 | ``` 19 | 20 | 2. **`pop()`**: 21 | El método `pop()` elimina y devuelve el elemento que está en la parte superior de la pila. Si la pila está vacía y se llama a este método, se lanzará una excepción `EmptyStackException`. Esta operación también tiene complejidad constante **O(1)**. 22 | ```java 23 | int elemento = stack.pop(); // Elimina y retorna el elemento tope de la pila 24 | ``` 25 | 26 | 3. **`peek()`**: 27 | El método `peek()` devuelve el elemento que está en la parte superior de la pila sin eliminarlo. Si se llama a este método cuando la pila está vacía, también lanzará una excepción `EmptyStackException`. La complejidad de esta operación es **O(1)**. 28 | ```java 29 | int tope = stack.peek(); // Retorna el elemento tope de la pila sin eliminarlo 30 | ``` 31 | 32 | 4. **`isEmpty()`**: 33 | Este método devuelve un valor booleano (`true` o `false`) indicando si la pila está vacía o no. Es una operación muy útil para evitar errores al intentar operar sobre una pila vacía. La complejidad de esta operación es **O(1)**. 34 | ```java 35 | boolean vacia = stack.isEmpty(); // Retorna true si la pila está vacía 36 | ``` 37 | 38 | 5. **`search(Object o)`**: 39 | El método `search()` busca un elemento específico en la pila y devuelve su posición, utilizando un índice basado en 1 (no en 0 como es común en Java). Si el elemento no se encuentra, devuelve `-1`. Este método puede tener una complejidad de **O(n)**, ya que en el peor de los casos debe recorrer todos los elementos de la pila para encontrar el objeto buscado. 40 | ```java 41 | int posicion = stack.search(10); // Busca el elemento 10 en la pila 42 | ``` 43 | 44 | ### Ejemplo de Uso de una Pila en Java 45 | 46 | Veamos un ejemplo de cómo usar una pila en Java para simular una funcionalidad básica de navegación de páginas web, donde el usuario puede regresar a la página anterior. 47 | 48 | ```java 49 | import java.util.Stack; 50 | 51 | public class NavegadorWeb { 52 | public static void main(String[] args) { 53 | // Crear una pila de páginas web 54 | Stack historialPaginas = new Stack<>(); 55 | 56 | // Simulación de navegación de páginas 57 | historialPaginas.push("Página 1"); 58 | historialPaginas.push("Página 2"); 59 | historialPaginas.push("Página 3"); 60 | 61 | System.out.println("Página actual: " + historialPaginas.peek()); 62 | 63 | // Retroceder una página 64 | historialPaginas.pop(); 65 | System.out.println("Página actual después de regresar: " + historialPaginas.peek()); 66 | 67 | // Verificar si hay páginas para regresar 68 | while (!historialPaginas.isEmpty()) { 69 | historialPaginas.pop(); 70 | System.out.println("Página actual después de regresar: " + (historialPaginas.isEmpty() ? "No hay más páginas" : historialPaginas.peek())); 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | ### Aplicaciones Comunes de las Pilas 77 | 78 | 1. **Navegadores web**: Para almacenar el historial de navegación de páginas, permitiendo volver a la página anterior. 79 | 2. **Deshacer/Rehacer** en editores de texto: Para gestionar las operaciones de deshacer y rehacer. 80 | 3. **Evaluación de expresiones**: En compiladores, las pilas se utilizan para evaluar expresiones matemáticas o evaluar operaciones aritméticas. 81 | 4. **Recursión**: Las llamadas a funciones recursivas utilizan una pila para almacenar las direcciones de retorno y los valores de las variables locales. 82 | 83 | ### Resumen 84 | 85 | Una pila en Java es una estructura de datos esencial que proporciona un mecanismo simple y eficiente para almacenar y manipular datos que deben seguir un orden LIFO. La clase `Stack` en Java ofrece una implementación lista para usar con métodos estándar como `push`, `pop`, `peek`, `isEmpty` y `search`, facilitando su utilización en una amplia variedad de aplicaciones. -------------------------------------------------------------------------------- /3.Java POO/26.Maps en java.md: -------------------------------------------------------------------------------- 1 | # Maps en Java: Una Explicación Completa 2 | 3 | #### ¿Qué es un Map en Java? 4 | 5 | En Java, un **Map** es una interfaz que forma parte del framework de colecciones (`java.util`) y representa una colección de pares clave-valor. Cada clave única se asocia a un valor, lo que permite acceder rápidamente a los datos asociados a una clave específica. Esta estructura es ideal para almacenar y recuperar información de manera eficiente. 6 | 7 | #### Características de los Maps 8 | 9 | - **Colección de pares clave-valor**: Un Map almacena elementos en pares, donde cada clave única se asocia con un valor. Esto permite una búsqueda rápida de datos mediante una clave. 10 | 11 | - **Claves únicas**: Dentro de un Map, cada clave debe ser única, pero los valores asociados a las claves pueden ser duplicados. 12 | 13 | - **Acceso eficiente a los datos**: Los Maps ofrecen una forma eficiente de manejar datos. Las operaciones de búsqueda, inserción y eliminación de elementos suelen ser rápidas. 14 | 15 | #### Implementaciones Comunes de Map en Java 16 | 17 | Java proporciona varias implementaciones de la interfaz `Map`, cada una con características únicas: 18 | 19 | 1. **HashMap**: Es una de las implementaciones más utilizadas y proporciona un mapeo basado en una tabla hash. Las operaciones como insertar, buscar y eliminar elementos tienen un rendimiento promedio de tiempo constante (O(1)), siempre que la función hash distribuya las claves de manera uniforme. No garantiza ningún orden para las claves o valores. 20 | 21 | 2. **TreeMap**: Implementa la interfaz `Map` utilizando un árbol rojo-negro (una estructura de árbol auto-balanceado). Ordena los elementos según el orden natural de las claves o según un comparador proporcionado. Las operaciones de inserción, eliminación y búsqueda tienen una complejidad de tiempo logarítmica (O(log n)). 22 | 23 | 3. **LinkedHashMap**: Combina las características de `HashMap` y una lista vinculada doblemente, manteniendo un orden de inserción de elementos. Es útil cuando necesitas preservar el orden de inserción de los elementos. Ofrece un rendimiento de tiempo constante (O(1)) para operaciones básicas como inserción, eliminación y búsqueda. 24 | 25 | 4. **Hashtable**: Es una implementación heredada de `Map`, que es similar a `HashMap`, pero es sincrónica, lo que la hace segura para su uso en entornos concurrentes. No permite claves ni valores nulos. 26 | 27 | 5. **ConcurrentHashMap**: Una variante de `HashMap` diseñada específicamente para entornos concurrentes. Permite operaciones concurrentes sin necesidad de sincronizar manualmente el acceso al mapa. Es altamente eficiente en aplicaciones multi-hilo. 28 | 29 | #### HashMap: Implementación Popular de Map 30 | 31 | **`HashMap`** es una de las implementaciones más comunes y utilizadas de la interfaz `Map` en Java. Utiliza una tabla hash para almacenar los pares clave-valor. Aquí hay un desglose más detallado de sus características: 32 | 33 | 1. **Eficiencia en la Búsqueda**: Las operaciones de búsqueda, inserción y eliminación en un `HashMap` tienen una complejidad de tiempo promedio de O(1). Esto significa que, en condiciones normales, estas operaciones se realizan en tiempo constante, gracias al uso de una función de hash que distribuye las claves de manera uniforme en la tabla hash. 34 | 35 | 2. **No Garantiza el Orden**: `HashMap` no garantiza ningún orden para sus elementos. Es decir, el orden de los pares clave-valor puede cambiar después de realizar operaciones como inserción y eliminación. 36 | 37 | 3. **Permite Claves y Valores Nulos**: A diferencia de algunas otras implementaciones, `HashMap` permite que tanto las claves como los valores sean `null`. Sin embargo, solo puede haber una clave `null` en un `HashMap`. 38 | 39 | 4. **Iteración a través de Entradas**: Puedes iterar a través de las entradas de un `HashMap` utilizando varios métodos: 40 | - **Usando un `Iterator`**: Puedes obtener un `Set` de entradas (`Map.Entry`) y usar un iterador para recorrerlas. 41 | - **Usando un bucle `for-each`**: Java 5 introdujo una forma más concisa de recorrer un `HashMap` usando un bucle `for-each`. 42 | 43 | #### Ejemplo Práctico de Uso de HashMap 44 | 45 | A continuación se presenta un ejemplo simple de cómo usar un `HashMap` en Java: 46 | 47 | ```java 48 | import java.util.HashMap; 49 | import java.util.Map; 50 | 51 | public class EjemploHashMap { 52 | public static void main(String[] args) { 53 | // Crear un nuevo HashMap 54 | Map inventario = new HashMap<>(); 55 | 56 | // Agregar elementos al HashMap 57 | inventario.put("Manzanas", 50); 58 | inventario.put("Naranjas", 30); 59 | inventario.put("Plátanos", 20); 60 | 61 | // Imprimir el contenido del HashMap 62 | System.out.println("Inventario: " + inventario); 63 | 64 | // Acceder a un valor específico usando la clave 65 | int cantidadManzanas = inventario.get("Manzanas"); 66 | System.out.println("Cantidad de Manzanas: " + cantidadManzanas); 67 | 68 | // Comprobar si una clave o valor existe 69 | boolean tieneNaranjas = inventario.containsKey("Naranjas"); 70 | System.out.println("¿Tiene naranjas? " + tieneNaranjas); 71 | 72 | // Eliminar un elemento del HashMap 73 | inventario.remove("Plátanos"); 74 | System.out.println("Inventario después de eliminar Plátanos: " + inventario); 75 | 76 | // Iterar sobre las entradas del HashMap 77 | for (Map.Entry entrada : inventario.entrySet()) { 78 | System.out.println("Fruta: " + entrada.getKey() + ", Cantidad: " + entrada.getValue()); 79 | } 80 | } 81 | } 82 | ``` 83 | 84 | #### Conclusión 85 | 86 | Los Maps en Java, y en particular el `HashMap`, son herramientas poderosas para manejar datos en pares clave-valor. Su uso eficiente de memoria y rendimiento constante en operaciones básicas lo hacen ideal para muchas aplicaciones. Dependiendo de las necesidades específicas, existen otras implementaciones de `Map` que ofrecen características adicionales como ordenamiento o seguridad en entornos concurrentes. -------------------------------------------------------------------------------- /3.Java POO/28.Relaciones entre Clases en Java.md: -------------------------------------------------------------------------------- 1 | # Relaciones entre Clases en Java 2 | 3 | Las relaciones entre clases en Java son fundamentales en la programación orientada a objetos (POO) porque permiten estructurar y organizar el comportamiento de un sistema de manera eficiente. Estas relaciones reflejan cómo los objetos de una clase interactúan o dependen de los objetos de otra clase. En Java, se pueden establecer diferentes tipos de relaciones entre clases como la herencia, la composición, la asociación y la agregación, que permiten crear un modelo sólido y flexible. 4 | 5 | ### Tipos de relaciones entre clases: 6 | 7 | #### 1. **Relación 1 a 1 (One-to-One)** 8 | En una relación 1 a 1, un objeto de una clase está relacionado exclusivamente con un objeto de otra clase. Es decir, cada instancia de la primera clase tiene una referencia única a una instancia de la segunda clase, y viceversa. 9 | 10 | Este tipo de relación se representa generalmente mediante la inclusión de un objeto como atributo dentro de otra clase. Un buen ejemplo podría ser la relación entre una clase `Persona` y su `Pasaporte`, donde cada persona tiene un único pasaporte, y un pasaporte pertenece a una única persona. 11 | 12 | ##### Ejemplo de código para una relación 1 a 1: 13 | ```java 14 | public class Persona { 15 | private int id; 16 | private String nombre; 17 | private Pasaporte pasaporte; // Relación 1 a 1 18 | 19 | // Constructor, getters y setters 20 | } 21 | 22 | public class Pasaporte { 23 | private int numero; 24 | private String paisEmision; 25 | 26 | // Constructor, getters y setters 27 | } 28 | ``` 29 | En este ejemplo, la clase `Persona` tiene una relación uno a uno con `Pasaporte`. Cada `Persona` está asociada a un único `Pasaporte`, y el `Pasaporte` está relacionado con una única `Persona`. 30 | 31 | #### 2. **Relación 1 a N (One-to-Many)** 32 | Una relación 1 a N implica que un objeto de una clase está relacionado con varios objetos de otra clase. En este tipo de relación, una instancia de la primera clase puede estar asociada a varias instancias de la segunda clase, pero cada instancia de la segunda clase está relacionada con una única instancia de la primera. 33 | 34 | Por ejemplo, una `Compra` puede tener múltiples `Items`, pero cada `Item` solo pertenece a una `Compra`. Esta relación se puede modelar utilizando colecciones como `List`, `Set` o `Map` para manejar múltiples objetos. 35 | 36 | ##### Ejemplo de código para una relación 1 a N: 37 | ```java 38 | import java.util.List; 39 | 40 | public class Compra { 41 | private int id; 42 | private String descripcion; 43 | private List listaItems; // Relación 1 a N 44 | 45 | // Constructor, getters y setters 46 | } 47 | 48 | public class Item { 49 | private int id; 50 | private String nombreItem; 51 | private double precio; 52 | 53 | // Constructor, getters y setters 54 | } 55 | ``` 56 | Aquí, la clase `Compra` tiene una lista de `Items`, lo que indica que una compra puede tener múltiples artículos. Sin embargo, cada `Item` está asociado a una única `Compra`. 57 | 58 | #### 3. **Relación N a N (Many-to-Many)** 59 | Una relación N a N es más compleja y ocurre cuando múltiples instancias de una clase están relacionadas con múltiples instancias de otra clase. Por ejemplo, muchos `Alumnos` pueden estar inscritos en muchas `Materias`, y cada `Materia` puede tener muchos `Alumnos`. 60 | 61 | Para implementar este tipo de relación en Java, se utilizan colecciones en ambas clases, de forma que cada objeto en una clase tenga una colección de objetos relacionados de la otra clase. En algunos casos, se puede utilizar una clase intermedia para gestionar esta relación y agregar información adicional (como notas, fechas de inscripción, etc.). 62 | 63 | ##### Ejemplo de código para una relación N a N: 64 | ```java 65 | import java.util.List; 66 | 67 | public class Alumno { 68 | private int id; 69 | private String nombre; 70 | private List listaMaterias; // Relación N a N 71 | 72 | // Constructor, getters y setters 73 | } 74 | 75 | public class Materia { 76 | private int id; 77 | private String nombre; 78 | private List listaAlumnos; // Relación N a N 79 | 80 | // Constructor, getters y setters 81 | } 82 | ``` 83 | En este ejemplo, tanto la clase `Alumno` como `Materia` tienen listas que contienen instancias de la otra clase. Esto modela una relación muchos a muchos, donde muchos alumnos pueden inscribirse en muchas materias y viceversa. 84 | 85 | ### **Beneficios y consideraciones de las relaciones entre clases:** 86 | - **Modelado realista del sistema:** Las relaciones entre clases permiten representar escenarios del mundo real, donde un objeto puede estar relacionado con otros en diversas formas (por ejemplo, personas, productos, transacciones). 87 | - **Facilidad de mantenimiento:** Tener relaciones bien definidas entre clases facilita la mantenibilidad del código, ya que cada clase tiene una responsabilidad clara y las interacciones entre ellas son predecibles. 88 | - **Reutilización de código:** Las relaciones permiten reutilizar código entre clases. Por ejemplo, si una clase se relaciona con varias otras, se pueden reutilizar sus métodos y propiedades en distintos contextos. 89 | 90 | Sin embargo, es importante considerar que a medida que las relaciones entre clases se vuelven más complejas (por ejemplo, muchas a muchas), es recomendable manejar adecuadamente la gestión de objetos y sus interacciones para evitar problemas de rendimiento y acoplamiento excesivo entre las clases. 91 | 92 | ### Conclusión: 93 | Las relaciones entre clases en Java son un pilar esencial de la programación orientada a objetos. Definen cómo interactúan los objetos entre sí y permiten que el sistema simule de manera eficiente las estructuras del mundo real. Ya sea mediante una relación 1 a 1, 1 a N o N a N, Java proporciona herramientas y patrones para modelar estas interacciones de manera clara y eficiente, ayudando a los desarrolladores a crear sistemas bien estructurados y fáciles de mantener. -------------------------------------------------------------------------------- /3.Java POO/30.ENUMS o enumeraciones en java.md: -------------------------------------------------------------------------------- 1 | # ENUMS o enumeraciones en java 2 | 3 | En Java, un `enum` (abreviatura de "enumeration") es un tipo especial de clase que representa un conjunto fijo de constantes. Estas constantes son únicas, lo que significa que no pueden cambiar durante la ejecución del programa. Los `enum` permiten agrupar un conjunto específico de valores bajo un mismo nombre, lo que es útil para trabajar con elementos que tienen un número limitado de opciones predefinidas, como los días de la semana, los meses del año, los puntos cardinales, o los estados de un semáforo. 4 | 5 | ### Características de los `enum` en Java 6 | 7 | 1. **Constantes Inmutables**: Cada elemento dentro de un `enum` es una instancia de ese `enum` y es una constante, es decir, su valor no cambia. Esto asegura que no se puedan introducir valores no previstos en el conjunto de opciones. 8 | 2. **Tipo Seguro**: Usar un `enum` permite trabajar de forma segura en cuanto al tipo de datos. Al definir un `enum`, restringes el conjunto de posibles valores, evitando errores como introducir una cadena no válida para un día de la semana. 9 | 3. **Instancias Únicas**: Cada constante de un `enum` es una instancia única y se puede comparar directamente usando el operador `==`, lo que mejora la claridad y la eficiencia del código. 10 | 11 | ### Ejemplo básico de un `enum` 12 | 13 | Supongamos que queremos definir los días de la semana. La definición sería algo así: 14 | 15 | ```java 16 | public enum Dia { 17 | LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO 18 | } 19 | ``` 20 | 21 | En este caso, `Dia` es el nombre del `enum` y contiene siete constantes: `LUNES`, `MARTES`, `MIERCOLES`, `JUEVES`, `VIERNES`, `SABADO`, y `DOMINGO`. Estas constantes representan los días de la semana y son los únicos valores posibles que el `enum` acepta. 22 | 23 | ### ¿Por qué usar `enum`? 24 | 25 | - **Legibilidad**: En lugar de usar valores como enteros o cadenas para representar estados o categorías específicas, el uso de `enum` hace que el código sea más legible. Por ejemplo, si usas enteros para representar los días de la semana (donde `1` es lunes, `2` es martes, etc.), no es intuitivo. En cambio, un `enum` como `Dia.LUNES` es más descriptivo. 26 | 27 | - **Evitar errores**: Al trabajar con un `enum`, Java te obliga a usar solo los valores predefinidos, lo que reduce los errores de codificación. Por ejemplo, si esperas un día de la semana, el uso de un `enum` evita que el programador pase una cadena como "Feriado" o cualquier otro valor que no sea válido. 28 | 29 | - **Comparación sencilla**: Como los `enum` son constantes y tienen una única instancia, es muy fácil compararlos usando el operador `==`, lo que garantiza una comparación eficiente. 30 | 31 | ### Métodos y funcionalidades adicionales 32 | 33 | Aunque los `enum` pueden parecer simples, tienen varias características avanzadas. Algunos de los métodos más comunes que se pueden usar con `enum` son: 34 | 35 | - **`values()`**: Retorna un array con todas las constantes definidas en el `enum`. 36 | 37 | ```java 38 | for (Dia dia : Dia.values()) { 39 | System.out.println(dia); 40 | } 41 | ``` 42 | 43 | - **`valueOf(String nombre)`**: Retorna la constante del `enum` cuyo nombre coincide con la cadena proporcionada. Si no encuentra una coincidencia, arroja una excepción `IllegalArgumentException`. 44 | 45 | ```java 46 | Dia dia = Dia.valueOf("LUNES"); 47 | ``` 48 | 49 | - **`ordinal()`**: Retorna la posición de la constante en el `enum`, empezando desde 0. Por ejemplo, `Dia.LUNES.ordinal()` devolverá 0, `Dia.MARTES.ordinal()` devolverá 1, y así sucesivamente. 50 | 51 | ```java 52 | System.out.println(Dia.MIERCOLES.ordinal()); // Imprime 2 53 | ``` 54 | 55 | ### `enum` con métodos y constructores 56 | 57 | Un `enum` en Java no está limitado a ser una simple lista de constantes. También puede incluir métodos, constructores y atributos. Esto te permite extender la funcionalidad de los `enum` de manera considerable. 58 | 59 | #### Ejemplo con constructores 60 | 61 | Imagina que quieres asignar un nombre completo a cada día de la semana, no solo su abreviatura. Puedes hacerlo de esta forma: 62 | 63 | ```java 64 | public enum Dia { 65 | LUNES("Lunes"), 66 | MARTES("Martes"), 67 | MIERCOLES("Miércoles"), 68 | JUEVES("Jueves"), 69 | VIERNES("Viernes"), 70 | SABADO("Sábado"), 71 | DOMINGO("Domingo"); 72 | 73 | private String nombreCompleto; 74 | 75 | Dia(String nombreCompleto) { 76 | this.nombreCompleto = nombreCompleto; 77 | } 78 | 79 | public String getNombreCompleto() { 80 | return nombreCompleto; 81 | } 82 | } 83 | ``` 84 | 85 | En este caso, hemos agregado un atributo `nombreCompleto` a cada constante del `enum`, y lo hemos inicializado a través de un constructor. Además, hemos proporcionado un método `getNombreCompleto()` para obtener el nombre completo de cada día. 86 | 87 | #### Uso de este `enum` con constructor 88 | 89 | ```java 90 | public class TestEnum { 91 | public static void main(String[] args) { 92 | for (Dia dia : Dia.values()) { 93 | System.out.println(dia + " - " + dia.getNombreCompleto()); 94 | } 95 | } 96 | } 97 | ``` 98 | 99 | Este código imprimiría algo como: 100 | 101 | ``` 102 | LUNES - Lunes 103 | MARTES - Martes 104 | MIERCOLES - Miércoles 105 | JUEVES - Jueves 106 | VIERNES - Viernes 107 | SABADO - Sábado 108 | DOMINGO - Domingo 109 | ``` 110 | 111 | ### Conclusión 112 | 113 | Los `enum` son una herramienta poderosa en Java que te permite definir un conjunto limitado de constantes con un tipo seguro y altamente legible. Al restringir las opciones posibles a un grupo fijo, reduces los errores potenciales y haces tu código más mantenible. Además, los `enum` en Java no son simplemente una lista de constantes; pueden tener métodos, atributos y lógica compleja, lo que les da una flexibilidad impresionante en situaciones más avanzadas. -------------------------------------------------------------------------------- /3.Java POO/34.JPA Controllers.md: -------------------------------------------------------------------------------- 1 | # JPA Controllers 2 | 3 | Un **JPA Controller** es una clase que sirve como un controlador para gestionar la interacción entre las entidades de la base de datos y la aplicación en Java. Estas clases controladoras se generan automáticamente al trabajar con JPA (Java Persistence API) y se encargan de gestionar las operaciones CRUD (crear, leer, actualizar, eliminar) sobre las entidades que están mapeadas en la base de datos. Cada entidad tiene un JPA Controller asociado, que facilita las operaciones de persistencia sin necesidad de escribir manualmente el código repetitivo. 4 | 5 | ### Creación de un JPA Controller 6 | 7 | Para crear un JPA Controller, sigues los siguientes pasos: 8 | 9 | 1. **Paso 1**: Haz clic derecho sobre el paquete de persistencia en tu proyecto. Luego selecciona `New` > `Other` > `Persistence` > `Jpa Controller Classes from Entity Classes`. Este asistente te permitirá generar automáticamente los controladores basados en las clases de entidad. 10 | 11 | 2. **Paso 2**: En la pantalla que aparece, verás todas las clases que has marcado como entidades. Estas entidades son clases Java que representan tablas en tu base de datos. Seleccionas las que quieres que tengan un controlador JPA y las agregas. 12 | 13 | 3. **Paso 3**: Asegúrate de seleccionar el paquete de persistencia adecuado como destino para la creación de los controladores. Esto asegura que las clases JPA Controller se coloquen en la ubicación correcta dentro de la estructura de tu proyecto. 14 | 15 | 4. **Paso 4**: Una vez generado el controlador, tu proyecto debe mostrar la estructura que incluye los controladores JPA para cada una de las entidades seleccionadas. Cada uno de estos controladores contiene métodos básicos para interactuar con la base de datos, tales como `create`, `edit`, `destroy`, `find`, entre otros. 16 | 17 | ### Configuración de un JPA Controller 18 | 19 | Después de haber creado el JPA Controller, es necesario configurarlo para que funcione correctamente con tu base de datos. Uno de los primeros pasos en esta configuración es el **constructor** de la clase. En el constructor, debes indicar cuál es la unidad de persistencia que el controlador va a utilizar. Esta unidad de persistencia está definida en el archivo `persistence.xml`, el cual se encuentra en la carpeta `META-INF` del proyecto. 20 | 21 | Dentro del constructor, se hace referencia a un objeto `EntityManagerFactory` (EMF), que es el responsable de crear los objetos `EntityManager`, los cuales son utilizados para interactuar con la base de datos. El EMF se inicializa con el nombre de la unidad de persistencia que se encuentra en el archivo `persistence.xml`. 22 | 23 | ### Controladora de Persistencia 24 | 25 | Para coordinar la interacción entre la lógica de la aplicación y los controladores JPA, es común crear una clase denominada **ControladoraPersistencia**. Esta clase actúa como un puente entre la lógica de negocio y las clases JPA Controller, delegando las solicitudes correspondientes a la entidad que debe gestionarlas. 26 | 27 | Dentro de la clase **ControladoraPersistencia**, se crea una instancia de cada controlador JPA que hayas generado. Por ejemplo, si tienes una entidad llamada `Producto`, habrá un controlador `ProductoJpaController`, y una instancia de este controlador estará presente en la **ControladoraPersistencia**. Esto permite centralizar y facilitar las operaciones de persistencia desde un único punto en la lógica de la aplicación. 28 | 29 | ### Ejemplo de Constructor de un JPA Controller 30 | 31 | ```java 32 | public class ProductoJpaController { 33 | private EntityManagerFactory emf = null; 34 | 35 | public ProductoJpaController(EntityManagerFactory emf) { 36 | this.emf = emf; 37 | } 38 | 39 | public EntityManager getEntityManager() { 40 | return emf.createEntityManager(); 41 | } 42 | 43 | public void create(Producto producto) { 44 | EntityManager em = null; 45 | try { 46 | em = getEntityManager(); 47 | em.getTransaction().begin(); 48 | em.persist(producto); 49 | em.getTransaction().commit(); 50 | } finally { 51 | if (em != null) { 52 | em.close(); 53 | } 54 | } 55 | } 56 | 57 | // Otros métodos como edit, destroy, find... 58 | } 59 | ``` 60 | 61 | En este ejemplo, el `EntityManagerFactory` (EMF) se pasa como parámetro al constructor de la clase. Luego, el método `getEntityManager` se encarga de crear un `EntityManager` que se utiliza en cada operación de persistencia. 62 | 63 | ### Resumen de Operaciones Básicas en un JPA Controller 64 | 65 | 1. **Create**: Permite crear un nuevo registro en la base de datos a partir de una instancia de una entidad. 66 | 2. **Edit**: Modifica un registro existente en la base de datos. 67 | 3. **Destroy**: Elimina un registro de la base de datos. 68 | 4. **Find**: Busca un registro en la base de datos utilizando el identificador (ID) de la entidad. 69 | 70 | Estos métodos ya están definidos en las clases JPA Controller, lo que facilita enormemente la gestión de las entidades en la base de datos sin necesidad de escribir consultas SQL manuales. 71 | 72 | ### Conclusión 73 | 74 | Los JPA Controllers son una herramienta poderosa que simplifica el manejo de la persistencia en aplicaciones Java al proporcionar un conjunto de clases y métodos predefinidos para interactuar con las entidades en la base de datos. Al generar automáticamente estos controladores y centralizar las operaciones a través de una **ControladoraPersistencia**, es posible gestionar de manera eficiente las operaciones CRUD y mantener un código limpio y bien organizado. -------------------------------------------------------------------------------- /3.Java POO/37.CRUD con JPA Find y FindEntities.md: -------------------------------------------------------------------------------- 1 | # CRUD con JPA Find y FindEntities 2 | 3 | CRUD (Create, Read, Update, Delete) es un conjunto de operaciones básicas que permiten manipular datos en una base de datos. JPA (Java Persistence API) es una especificación que facilita el mapeo de objetos Java a bases de datos relacionales. Dentro de las operaciones de lectura en JPA, los métodos `find` y `findEntities` son fundamentales para realizar consultas y recuperar datos almacenados en la base de datos. 4 | 5 | ### Método `find` 6 | 7 | El método `find` de JPA está diseñado para buscar y recuperar un único objeto de entidad en la base de datos utilizando su clave primaria. Se suele invocar cuando se desea obtener un registro exacto basado en un identificador único. Este identificador es la clave primaria que la entidad tiene asignada. A continuación se desglosa el funcionamiento del método: 8 | 9 | #### Parámetros 10 | 1. **Clase de la Entidad**: El primer parámetro que recibe el método `find` es la clase del objeto que se desea recuperar. Esta clase está mapeada a una tabla en la base de datos, y cada instancia de esta clase corresponde a una fila en esa tabla. 11 | 12 | 2. **Clave Primaria**: El segundo parámetro es el valor de la clave primaria del objeto que se quiere buscar en la base de datos. JPA utiliza este valor para identificar unívocamente el registro en la tabla. 13 | 14 | #### Proceso Interno 15 | Cuando se llama al método `find`, JPA ejecuta una consulta SQL del tipo `SELECT` que busca en la tabla correspondiente el registro cuya clave primaria coincida con el valor proporcionado. Si encuentra un registro con esa clave, devuelve una instancia de la entidad correspondiente con todos los atributos llenos a partir de los datos de la base de datos. 16 | 17 | #### Resultado 18 | - Si encuentra el registro: Retorna una instancia de la entidad solicitada con sus atributos cargados desde la base de datos. 19 | - Si no encuentra el registro: Devuelve `null`, lo que indica que no hay ningún objeto con el identificador proporcionado. 20 | 21 | #### Ejemplo 22 | Imaginemos una entidad `Usuario` con una clave primaria `id`: 23 | 24 | ```java 25 | Usuario usuario = entityManager.find(Usuario.class, 1L); 26 | ``` 27 | En este caso, el método busca en la tabla de `Usuario` el registro cuya clave primaria es `1`. Si lo encuentra, devuelve un objeto `Usuario` con todos sus atributos llenos, como nombre, correo, etc. Si no existe un usuario con ese `id`, el resultado será `null`. 28 | 29 | ### Método `findEntities` 30 | 31 | Mientras que el método `find` está orientado a la búsqueda de un único objeto en la base de datos, el método `findEntities` permite recuperar una lista de objetos de una clase de entidad específica. Este método es útil cuando queremos obtener todos los registros de una tabla o cuando queremos aplicar criterios adicionales para filtrar los resultados. 32 | 33 | #### Parámetros 34 | - **Clase de la Entidad**: Al igual que el método `find`, `findEntities` también recibe como parámetro la clase de entidad de la cual se desea obtener los registros. Este parámetro le indica a JPA cuál es la tabla que se va a consultar. 35 | 36 | #### Proceso Interno 37 | Al invocar `findEntities`, JPA genera una consulta del tipo `SELECT * FROM` para obtener todos los registros de la tabla mapeada a la clase de la entidad especificada. La consulta trae todas las filas de la tabla y por cada una crea una instancia de la clase de entidad correspondiente, con los atributos llenos según los valores en la base de datos. 38 | 39 | #### Resultado 40 | - Devuelve una **lista de objetos** de la clase de entidad. Esta lista puede contener: 41 | - Todos los registros de la tabla, si no se ha aplicado ninguna restricción. 42 | - Un subconjunto de registros si se han especificado restricciones en la implementación del método (en caso de haber métodos personalizados basados en `findEntities`). 43 | 44 | - Si no hay registros en la tabla: Devuelve una lista vacía. 45 | 46 | #### Ejemplo 47 | Consideremos una entidad `Producto` que representa los productos de una tienda: 48 | 49 | ```java 50 | List productos = productoDAO.findEntities(); 51 | ``` 52 | 53 | En este caso, el método `findEntities` recupera todos los productos de la tabla `Producto` y los devuelve en forma de una lista. Si no hay productos en la tabla, el método devolverá una lista vacía. 54 | 55 | ### Diferencias Clave entre `find` y `findEntities` 56 | - **Objetivo**: El método `find` se utiliza para recuperar un solo registro a partir de su clave primaria, mientras que `findEntities` recupera todos los registros de una tabla o los registros que cumplan con ciertos criterios. 57 | - **Resultado**: `find` devuelve una sola instancia de la entidad o `null` si no existe, mientras que `findEntities` siempre devuelve una lista (vacía si no hay registros). 58 | - **Performance**: `find` es más eficiente cuando se necesita obtener un solo registro, mientras que `findEntities` puede generar una carga mayor sobre la base de datos cuando se tienen muchos registros en la tabla. 59 | 60 | ### Ejemplo Práctico de Uso en un CRUD 61 | Supongamos que estamos desarrollando un sistema de gestión de empleados con una clase `Empleado`. Queremos implementar las funcionalidades de "Leer" (Read) del CRUD. 62 | 63 | #### Recuperar un Empleado por su ID: 64 | ```java 65 | Empleado empleado = entityManager.find(Empleado.class, 1001L); 66 | if (empleado != null) { 67 | System.out.println("Empleado encontrado: " + empleado.getNombre()); 68 | } else { 69 | System.out.println("No se encontró ningún empleado con ese ID."); 70 | } 71 | ``` 72 | 73 | #### Recuperar todos los Empleados: 74 | ```java 75 | List empleados = empleadoDAO.findEntities(); 76 | if (!empleados.isEmpty()) { 77 | for (Empleado emp : empleados) { 78 | System.out.println("Empleado: " + emp.getNombre()); 79 | } 80 | } else { 81 | System.out.println("No hay empleados en la base de datos."); 82 | } 83 | ``` 84 | 85 | ### Conclusión 86 | 87 | Los métodos `find` y `findEntities` son esenciales en cualquier aplicación que utilice JPA, ya que permiten realizar consultas eficientes sobre la base de datos. Mientras que `find` está orientado a la búsqueda de un único registro mediante su clave primaria, `findEntities` permite obtener múltiples registros, facilitando así la implementación de las operaciones de lectura en el CRUD. El uso adecuado de estos métodos no solo asegura una buena gestión de los datos, sino que también optimiza el rendimiento de la aplicación cuando se maneja un gran volumen de información. -------------------------------------------------------------------------------- /4.Spring Boot/46.Primer API con Spring Boot.md: -------------------------------------------------------------------------------- 1 | # Primer API con Spring Boot 2 | 3 | ## PASO 1 4 | Primero, vamos a crear un nuevo proyecto utilizando Initializr, como ya lo hemos hecho en "clases" anteriores ([Spring Initializr](./43.Spring%20Initializr.md)). Una vez que el proyecto esté configurado y funcionando en el IDE, crearemos un paquete llamado `Controller`. 5 | 6 | ![image](https://github.com/user-attachments/assets/5c95f7e7-17db-4d60-92ce-893227481fd6) 7 | ![image](https://github.com/user-attachments/assets/cb26faf9-bc30-4658-b720-35dbe2c3f9e4) 8 | 9 | 10 | ## PASO 2 11 | El paquete creado en el paso anterior representará la capa de control de nuestro proyecto, siguiendo el patrón de diseño MVC (Modelo-Vista-Controlador). Dentro de este paquete, vamos a definir una clase que se encargará de gestionar las solicitudes que lleguen a nuestro sistema. Esta clase funcionará como controlador, y para ello usaremos la anotación `@RestController` para mapearla correctamente. 12 | 13 | ![image](https://github.com/user-attachments/assets/61c2dd3e-567b-46d9-a755-5323f45fd431) 14 | ![image](https://github.com/user-attachments/assets/a2faaa20-6bb3-4a92-8a14-d94b8262e14d) 15 | 16 | 17 | ## PASO 3 18 | Luego, crearemos un método llamado `sayHello` (respetando la convención de usar nombres de métodos en inglés). Este método responderá con un mensaje cuando reciba una solicitud HTTP GET. Para lograrlo, utilizaremos la anotación `@GetMapping` para mapear el endpoint que manejará las solicitudes GET. En clases posteriores veremos más detalles sobre esta anotación, pero por el momento la utilizaremos de forma básica. 19 | 20 | ![image](https://github.com/user-attachments/assets/69f82170-6a56-4f6c-9cc7-b3032e906196) 21 | 22 | 23 | ## PASO 4 24 | Finalmente, es hora de probar nuestra API. Para ello, ejecutaremos la aplicación e ingresaremos en el navegador la URL local de nuestra API. Esta URL, junto con el puerto, se muestra en la consola de Spring Boot al ejecutar la app. En nuestro caso, la URL será: [https://localhost:8080/](https://localhost:8080/) (asegúrate de usar el puerto que has configurado o el que Spring Boot indique). 25 | 26 | ![image](https://github.com/user-attachments/assets/07c3d0e2-f559-4d37-8c11-3eb459e98688) 27 | ![image](https://github.com/user-attachments/assets/a77aea82-f6aa-4d0e-b844-1fa0c5d9573e) 28 | 29 | 30 | Si todo está bien, deberíamos ver en el navegador el mensaje que hemos definido en el método `sayHello`. 31 | -------------------------------------------------------------------------------- /4.Spring Boot/47.@GetMapping y @PathVariable.md: -------------------------------------------------------------------------------- 1 | # @GetMapping y Parámetros @PathVariable 2 | 3 | En Spring Boot, las anotaciones `@GetMapping` y `@PathVariable` son fundamentales para construir controladores REST que manejen peticiones HTTP GET de forma eficiente y flexible. A continuación, te explico en detalle cómo funcionan y cómo pueden interactuar en una aplicación. 4 | 5 | ### @GetMapping 6 | 7 | `@GetMapping` es una anotación en Spring Boot que se utiliza para mapear solicitudes HTTP GET a métodos específicos en un controlador. Esto significa que cuando un cliente (navegador, Postman u otro servicio) realiza una petición GET a una URL particular, el método marcado con `@GetMapping` será ejecutado. 8 | 9 | #### Funcionamiento: 10 | - **Solicitudes GET**: Este tipo de solicitudes se utilizan comúnmente para obtener datos desde el servidor. A diferencia de POST, GET no modifica datos, sino que se enfoca en la consulta. 11 | - **Especificación de Rutas**: Puedes asociar `@GetMapping` a una URL específica. Si no se especifica ninguna URL, el método se asigna al directorio raíz del servidor ("/"), pero en la práctica, casi siempre se define un path para cada endpoint. 12 | 13 | Por ejemplo: 14 | ```java 15 | @GetMapping("/hola") 16 | public String saludar() { 17 | return "Hola, bienvenido a nuestra API"; 18 | } 19 | 20 | @GetMapping("/chau") 21 | public String despedir() { 22 | return "Adiós, hasta luego"; 23 | } 24 | ``` 25 | En este ejemplo, si accedes a `/hola`, recibirás el mensaje "Hola, bienvenido a nuestra API". Mientras que al acceder a `/chau`, obtendrás "Adiós, hasta luego". 26 | 27 | #### Ejemplo de uso sin ruta: 28 | Si no se especifica una ruta con `@GetMapping`, como en el siguiente ejemplo: 29 | 30 | ```java 31 | @GetMapping 32 | public String saludoGenerico() { 33 | return "Bienvenido a la página principal"; 34 | } 35 | ``` 36 | Cualquier solicitud a la raíz ("/") de la aplicación será manejada por este método, pero en aplicaciones más grandes o complejas es común evitar esto para evitar conflictos con otros endpoints. 37 | 38 | ### @PathVariable 39 | 40 | `@PathVariable` es otra anotación muy importante que se utiliza para extraer información dinámica de la URL, permitiendo así una mayor flexibilidad en las solicitudes. 41 | 42 | #### Funcionamiento: 43 | - **Variables de ruta**: Con `@PathVariable`, puedes definir partes de la URL como variables que se pasan como argumentos al método. Esto es útil cuando necesitas que un endpoint responda de forma personalizada según el valor proporcionado en la URL. 44 | 45 | Por ejemplo: 46 | ```java 47 | @GetMapping("/saludo/{nombre}") 48 | public String saludoPersonalizado(@PathVariable String nombre) { 49 | return "Hola " + nombre + ", bienvenido a nuestra API"; 50 | } 51 | ``` 52 | En este caso, si realizas una solicitud a `/saludo/Agustin`, la respuesta será "Hola Agustin, bienvenido a nuestra API". Aquí, la variable `nombre` toma el valor de la parte dinámica de la URL (`/saludo/{nombre}`). 53 | 54 | - **Tipos de variables**: Las variables en la ruta pueden ser de cualquier tipo de dato, como `String`, `int`, `long`, etc. Spring se encarga automáticamente de convertir la variable de la URL al tipo adecuado si es posible. Un ejemplo más avanzado sería: 55 | 56 | ```java 57 | @GetMapping("/producto/{id}") 58 | public String obtenerProducto(@PathVariable int id) { 59 | return "Detalles del producto con ID: " + id; 60 | } 61 | ``` 62 | En este caso, si accedes a `/producto/123`, la variable `id` toma el valor `123`, y puedes usarlo para buscar información en una base de datos o en otro servicio. 63 | 64 | ### Interacción entre @GetMapping y @PathVariable 65 | 66 | Ambas anotaciones se complementan para crear endpoints dinámicos y personalizados en Spring Boot. Por ejemplo, puedes tener múltiples rutas en tu controlador que manejan diferentes patrones de URL utilizando `@GetMapping` y `@PathVariable` conjuntamente. 67 | 68 | Imagina una aplicación que maneja una tienda online con productos: 69 | 70 | ```java 71 | @RestController 72 | public class ProductoController { 73 | 74 | @GetMapping("/productos") 75 | public List listarProductos() { 76 | // Retorna una lista de productos 77 | return productoService.obtenerTodosLosProductos(); 78 | } 79 | 80 | @GetMapping("/productos/{id}") 81 | public Producto obtenerProductoPorId(@PathVariable int id) { 82 | // Busca y retorna un producto por su ID 83 | return productoService.obtenerProductoPorId(id); 84 | } 85 | } 86 | ``` 87 | - Si realizas una solicitud GET a `/productos`, recibirás una lista completa de productos. 88 | - Si realizas una solicitud GET a `/productos/5`, obtendrás los detalles del producto con el ID `5`. 89 | 90 | Esto es extremadamente útil cuando necesitas manejar recursos de manera eficiente en una API RESTful, permitiendo que los clientes realicen solicitudes específicas basadas en identificadores. 91 | 92 | ### Resumen: 93 | - **`@GetMapping`**: Se utiliza para definir métodos que manejan solicitudes HTTP GET. Puedes asignar una URL específica al método para que responda a solicitudes en esa ruta. 94 | - **`@PathVariable`**: Permite capturar partes dinámicas de la URL y pasarlas como argumentos al método, haciendo que las solicitudes GET sean más flexibles y contextuales. 95 | 96 | Juntos, `@GetMapping` y `@PathVariable` permiten crear endpoints dinámicos y personalizables en una API, haciendo que el sistema sea más eficiente y fácil de usar tanto para desarrolladores como para usuarios finales. -------------------------------------------------------------------------------- /4.Spring Boot/48.@RequestParam .md: -------------------------------------------------------------------------------- 1 | # @RequestParam 2 | 3 | La anotación `@RequestParam` en Spring MVC se utiliza para capturar parámetros que se envían en una solicitud HTTP, generalmente mediante el método GET, aunque también puede utilizarse en otros métodos HTTP. Los parámetros son enviados como parte de la URL después del símbolo de interrogación (`?`) y están separados por el símbolo `&`. A diferencia de `@PathVariable`, donde los parámetros son parte del propio path de la URL, con `@RequestParam` los valores se pasan explícitamente como pares clave-valor. 4 | 5 | ### ¿Cómo funciona `@RequestParam`? 6 | 7 | Cuando se hace una solicitud HTTP con parámetros, la estructura de la URL podría verse así: 8 | 9 | ``` 10 | http://ejemplo.com/api/usuarios?nombre=Juan&edad=25 11 | ``` 12 | 13 | En este caso, los parámetros `nombre` y `edad` son capturados por el método en el backend a través de la anotación `@RequestParam`. Estos valores pueden luego ser procesados por el método del controlador. 14 | 15 | ### Ejemplo básico: 16 | 17 | Imagina que tienes un controlador en Spring con un método que maneja una solicitud GET para obtener información sobre un usuario: 18 | 19 | ```java 20 | @GetMapping("/api/usuarios") 21 | public String obtenerUsuario(@RequestParam String nombre, @RequestParam int edad) { 22 | return "Nombre: " + nombre + ", Edad: " + edad; 23 | } 24 | ``` 25 | 26 | Este método espera recibir dos parámetros de la solicitud: `nombre` y `edad`. Cuando el cliente hace una solicitud como esta: 27 | 28 | ``` 29 | http://ejemplo.com/api/usuarios?nombre=Juan&edad=25 30 | ``` 31 | 32 | El controlador capturará esos parámetros y responderá con: 33 | 34 | ``` 35 | Nombre: Juan, Edad: 25 36 | ``` 37 | 38 | ### ¿Cuándo usar `@RequestParam`? 39 | 40 | `@RequestParam` es ideal para situaciones donde quieres que los datos se envíen como parámetros de la URL en lugar de como parte del path. Este método es común en formularios HTML que utilizan el método GET, donde los datos del formulario se codifican en la URL como parámetros de consulta. 41 | 42 | Por ejemplo, un formulario de búsqueda puede enviar criterios de búsqueda como parámetros de consulta en la URL: 43 | 44 | ``` 45 | http://ejemplo.com/busqueda?query=java&pagina=2 46 | ``` 47 | 48 | Aquí, el parámetro `query` contiene el término de búsqueda "java" y `pagina` indica que se está solicitando la página 2 de los resultados. 49 | 50 | ### Opciones adicionales con `@RequestParam` 51 | 52 | 1. **Parámetros opcionales**: No todos los parámetros son obligatorios. Puedes hacer que un parámetro sea opcional asignando un valor predeterminado con `defaultValue` o utilizando `required = false`: 53 | 54 | ```java 55 | @GetMapping("/api/usuarios") 56 | public String obtenerUsuario(@RequestParam(required = false, defaultValue = "Anónimo") String nombre) { 57 | return "Nombre: " + nombre; 58 | } 59 | ``` 60 | 61 | En este caso, si no se proporciona el parámetro `nombre`, la variable tomará el valor "Anónimo". 62 | 63 | 2. **Mapeo de múltiples parámetros**: Si no conoces de antemano cuántos parámetros vas a recibir, puedes capturarlos en un `Map`: 64 | 65 | ```java 66 | @GetMapping("/api/usuarios") 67 | public String obtenerParametros(@RequestParam Map parametros) { 68 | return parametros.toString(); 69 | } 70 | ``` 71 | 72 | Esto te permitirá capturar todos los parámetros sin definir cada uno explícitamente. 73 | 74 | ### Comparación con `@PathVariable` 75 | 76 | Aunque tanto `@RequestParam` como `@PathVariable` permiten capturar valores de la URL, sus usos son distintos: 77 | 78 | - **@RequestParam**: Captura parámetros que se envían como pares clave-valor en la URL después del signo `?`. Ideal para formularios y filtros. 79 | 80 | Ejemplo de URL: 81 | ``` 82 | http://ejemplo.com/api/usuarios?nombre=Juan&edad=25 83 | ``` 84 | 85 | - **@PathVariable**: Captura variables que forman parte del path de la URL. Es útil cuando los valores son esenciales para identificar un recurso específico. 86 | 87 | Ejemplo de URL con `@PathVariable`: 88 | ``` 89 | http://ejemplo.com/api/usuarios/Juan/25 90 | ``` 91 | 92 | ### Resumen: 93 | 94 | `@RequestParam` es una anotación poderosa que te permite recibir parámetros de consulta de manera flexible. Su uso es clave cuando necesitas recibir datos como pares clave-valor en la URL, siendo ideal para formularios o filtros de búsqueda. A diferencia de `@PathVariable`, que extrae datos directamente del path de la URL, `@RequestParam` permite una manera más explícita y ordenada de capturar parámetros en la solicitud HTTP, separándolos claramente del recurso que se está solicitando. -------------------------------------------------------------------------------- /4.Spring Boot/49.Que es JSON.md: -------------------------------------------------------------------------------- 1 | # Que es JSON? 2 | 3 | JSON, que significa “JavaScript Object Notation”, es un formato de texto ligero y ampliamente utilizado para intercambiar datos entre diferentes sistemas, especialmente a través del protocolo HTTP. Aunque se originó en el lenguaje JavaScript, JSON es un formato independiente de cualquier lenguaje de programación, lo que lo convierte en una herramienta versátil y universal para la comunicación entre aplicaciones que utilizan lenguajes distintos. 4 | 5 | ### ¿Cómo funciona JSON? 6 | 7 | JSON se basa en el concepto de pares “clave-valor”. Cada clave es un identificador único (una cadena de texto) y cada valor puede ser de diversos tipos: cadenas de texto, números, booleanos, arrays (listas de valores) u otros objetos JSON. Este formato de datos es fácil de leer para los humanos y sencillo de procesar para las máquinas. 8 | 9 | #### Estructura básica de un objeto JSON 10 | Un objeto en JSON se representa con llaves `{}`, donde se define un conjunto de claves y valores. La clave siempre es una cadena de texto, mientras que el valor puede variar en tipo de dato. A continuación, se muestra un ejemplo simple de un objeto JSON: 11 | 12 | ```json 13 | { 14 | "nombre": "Cristiano Ronaldo", 15 | "edad": 38, 16 | "nacionalidad": "portugués" 17 | } 18 | ``` 19 | 20 | En este caso: 21 | - **“nombre”** es la clave y **“Cristiano Ronaldo”** es su valor (una cadena de texto). 22 | - **“edad”** es la clave y **38** es su valor (un número). 23 | - **“nacionalidad”** es la clave y **“portugués”** es su valor (una cadena de texto). 24 | 25 | ### Arrays en JSON 26 | Además de los objetos, JSON permite almacenar conjuntos de valores múltiples dentro de arrays, los cuales se representan con corchetes `[]`. Esto es útil cuando se quiere almacenar una lista de elementos, como equipos de fútbol en los que ha jugado Cristiano Ronaldo. Un ejemplo de JSON que incluye un array sería el siguiente: 27 | 28 | ```json 29 | { 30 | "nombre": "Cristiano Ronaldo", 31 | "edad": 38, 32 | "equipos": ["Sporting CP", "Manchester United", "Real Madrid", "Juventus", "Al-Nassr"] 33 | } 34 | ``` 35 | 36 | Aquí, la clave **“equipos”** tiene como valor un array que contiene una lista de cadenas de texto, representando los equipos en los que ha jugado. 37 | 38 | ### Objetos anidados 39 | Otra característica potente de JSON es la capacidad de anidar objetos dentro de otros objetos. Esto permite una representación más rica y estructurada de los datos. Por ejemplo, si quisiéramos añadir más detalles sobre los equipos, podríamos crear un JSON más complejo: 40 | 41 | ```json 42 | { 43 | "nombre": "Cristiano Ronaldo", 44 | "edad": 38, 45 | "equipos": [ 46 | { 47 | "nombre": "Manchester United", 48 | "pais": "Inglaterra", 49 | "años": [2003, 2009] 50 | }, 51 | { 52 | "nombre": "Real Madrid", 53 | "pais": "España", 54 | "años": [2009, 2018] 55 | } 56 | ] 57 | } 58 | ``` 59 | 60 | En este caso, cada elemento del array **“equipos”** es a su vez un objeto que contiene más detalles sobre el equipo, como su país y los años en los que jugó allí. 61 | 62 | ### JSON con varios objetos 63 | JSON también permite trabajar con múltiples objetos dentro de un mismo archivo o mensaje. Para separar los objetos, se usa una coma `,`. Un ejemplo que muestra varios objetos podría ser: 64 | 65 | ```json 66 | [ 67 | { 68 | "nombre": "Cristiano Ronaldo", 69 | "edad": 38, 70 | "equipos": ["Sporting CP", "Manchester United", "Real Madrid", "Juventus", "Al-Nassr"] 71 | }, 72 | { 73 | "nombre": "Lionel Messi", 74 | "edad": 36, 75 | "equipos": ["Barcelona", "Paris Saint-Germain", "Inter Miami"] 76 | } 77 | ] 78 | ``` 79 | 80 | En este caso, se representa una lista de dos objetos, cada uno describiendo a un jugador de fútbol. 81 | 82 | ### ¿Por qué es importante JSON? 83 | JSON es fundamental en el mundo del desarrollo web y la integración de sistemas debido a su simplicidad, flexibilidad y amplio soporte. Es el formato de intercambio de datos más común en APIs REST (un tipo de servicio web que utiliza HTTP) y su popularidad proviene de varias ventajas: 84 | 85 | - **Simplicidad**: JSON es fácil de entender tanto para desarrolladores como para los sistemas que lo procesan. 86 | - **Compatibilidad**: Se puede generar y consumir en prácticamente todos los lenguajes de programación (JavaScript, Python, Java, PHP, etc.). 87 | - **Ligereza**: Al ser un formato de texto plano, es mucho más ligero que otros formatos como XML, lo que optimiza el rendimiento y la velocidad de transmisión de datos. 88 | - **Estandarización**: JSON es un estándar ampliamente adoptado, lo que significa que cualquier API que lo utilice será compatible con una gran variedad de plataformas y tecnologías. 89 | 90 | ### Conclusión 91 | Conocer y manejar JSON es esencial para cualquier desarrollador que trabaje con APIs y aplicaciones modernas. Su uso extendido en servicios web, aplicaciones móviles, bases de datos y muchas otras áreas lo convierte en una herramienta imprescindible para la comunicación y el intercambio de datos entre sistemas de manera eficiente y comprensible. -------------------------------------------------------------------------------- /4.Spring Boot/50.@PostMapping + @RequestBody.md: -------------------------------------------------------------------------------- 1 | ### Explicación Detallada de @PostMapping y @RequestBody en Spring Boot 2 | 3 | #### @PostMapping 4 | En Spring Boot, la anotación `@PostMapping` se utiliza para manejar solicitudes HTTP del tipo **POST** en los controladores de la aplicación. Es el equivalente a `@GetMapping`, que se usa para solicitudes **GET**, pero en lugar de devolver datos, las solicitudes POST generalmente se usan para **enviar datos al servidor**, como parte de la creación o actualización de recursos. 5 | 6 | La anotación `@PostMapping` se coloca antes del método del controlador que se ejecutará cuando se reciba una solicitud POST en una URL específica. Al usarla, le indicamos al controlador qué ruta y qué tipo de solicitud HTTP manejará. Esto hace que sea fácil y claro trabajar con solicitudes POST, especialmente cuando estás desarrollando APIs RESTful. 7 | 8 | #### Ejemplo de uso básico de @PostMapping: 9 | ```java 10 | @PostMapping("/cliente") 11 | public String nuevoCliente() { 12 | return "Cliente creado"; 13 | } 14 | ``` 15 | 16 | En este ejemplo simple, cuando se hace una solicitud POST a la URL `/cliente`, el método `nuevoCliente` es ejecutado. Sin embargo, este método no está haciendo nada con los datos recibidos todavía. Para manejar datos enviados en el cuerpo de la solicitud, es donde entra `@RequestBody`. 17 | 18 | --- 19 | 20 | #### @RequestBody 21 | La anotación `@RequestBody` es el complemento perfecto de `@PostMapping` cuando necesitamos **recibir datos en el cuerpo de la solicitud** HTTP. Permite que Spring mapee automáticamente los datos que vienen en el cuerpo de una solicitud POST a un **objeto Java**, haciendo mucho más fácil trabajar con la información recibida. 22 | 23 | Cuando usamos `@RequestBody`, Spring convierte el contenido del cuerpo de la solicitud (que normalmente está en formato JSON o XML) en un objeto de Java, utilizando un proceso de deserialización. Esto permite que el backend manipule esos datos de manera sencilla, como si fueran objetos de Java nativos. 24 | 25 | #### Ejemplo de uso de @PostMapping con @RequestBody: 26 | Supongamos que tenemos una clase `Cliente` con los atributos `id`, `nombre`, y `apellido`, y queremos recibir los datos de un nuevo cliente desde una solicitud POST. 27 | 28 | ```java 29 | @Data // Lombok para generar getters y setters automáticamente 30 | public class Cliente { 31 | private Long id; 32 | private String nombre; 33 | private String apellido; 34 | } 35 | ``` 36 | 37 | Ahora en el controlador: 38 | ```java 39 | @RestController 40 | public class ClienteController { 41 | 42 | @PostMapping("/cliente") 43 | public String nuevoCliente(@RequestBody Cliente cliente) { 44 | // Aquí ya tenemos un objeto Cliente, podemos trabajar con él 45 | System.out.println("Cliente recibido: " + cliente.getNombre() + " " + cliente.getApellido()); 46 | return "Cliente creado exitosamente"; 47 | } 48 | } 49 | ``` 50 | 51 | En este caso, cuando se hace una solicitud POST a `/cliente` con un cuerpo JSON que represente un cliente, como: 52 | ```json 53 | { 54 | "id": 1, 55 | "nombre": "Juan", 56 | "apellido": "Pérez" 57 | } 58 | ``` 59 | 60 | El método `nuevoCliente` recibirá este JSON y lo convertirá en una instancia de la clase `Cliente`. Así podemos acceder a las propiedades del cliente dentro del código. 61 | 62 | --- 63 | 64 | ### ¿Cómo Funciona el Proceso Interno? 65 | 1. **Solicitud POST**: Cuando se hace una solicitud POST a `/cliente`, los datos que viajan en el cuerpo de la solicitud (por ejemplo, un JSON) son enviados al servidor. 66 | 2. **Deserialización**: Spring automáticamente convierte esos datos del formato JSON en un objeto de Java (en este caso, un objeto `Cliente`). 67 | 3. **Acción**: El método en el controlador toma este objeto y puede procesarlo, guardarlo en una base de datos, etc. 68 | 4. **Respuesta**: Después de procesar los datos, el servidor envía una respuesta (en este caso, un mensaje simple). 69 | 70 | ### Beneficios de Usar @RequestBody 71 | - **Automatización**: No es necesario manualmente analizar el cuerpo de la solicitud; Spring lo hace por ti. 72 | - **Flexibilidad**: Puedes trabajar directamente con objetos Java en lugar de manipular manualmente datos en formato JSON o XML. 73 | - **Seguridad**: A través de la validación (que puede ser agregada), puedes asegurar que los datos recibidos son correctos antes de procesarlos. 74 | 75 | --- 76 | 77 | ### Pruebas de los Endpoints POST 78 | Una diferencia clave entre GET y POST es cómo se prueban. Las solicitudes GET pueden probarse directamente desde el navegador porque los datos se envían a través de la URL, mientras que las solicitudes POST envían los datos en el cuerpo de la solicitud, lo cual no es fácil de replicar con un simple navegador. 79 | 80 | Para simular solicitudes POST, es necesario usar herramientas como **Postman** o **cURL**, que permiten enviar solicitudes HTTP con diferentes métodos (POST, PUT, DELETE, etc.) y con cuerpos personalizados (JSON, XML, etc.). En Postman, puedes seleccionar el método POST, definir la URL del endpoint y agregar un cuerpo en formato JSON para enviar una solicitud que simule la interacción entre un cliente y un servidor. 81 | 82 | #### Ejemplo de prueba de solicitud POST en Postman: 83 | 1. Abrir Postman. 84 | 2. Seleccionar el método POST. 85 | 3. Especificar la URL: `http://localhost:8080/cliente`. 86 | 4. En la pestaña de **Body**, seleccionar **raw** y **JSON**. 87 | 5. Pegar el siguiente JSON en el cuerpo: 88 | ```json 89 | { 90 | "id": 1, 91 | "nombre": "Juan", 92 | "apellido": "Pérez" 93 | } 94 | ``` 95 | 6. Enviar la solicitud y revisar la respuesta del servidor. 96 | 97 | --- 98 | 99 | ### Conclusión 100 | El uso de `@PostMapping` y `@RequestBody` en Spring Boot facilita la creación de endpoints para recibir y manejar datos enviados a través de solicitudes POST. `@PostMapping` se encarga de mapear las solicitudes HTTP POST a un método específico, mientras que `@RequestBody` convierte automáticamente los datos del cuerpo de la solicitud en objetos Java que podemos manipular dentro de nuestra aplicación. Esto permite una mayor flexibilidad y simplicidad a la hora de desarrollar aplicaciones web y APIs RESTful. -------------------------------------------------------------------------------- /4.Spring Boot/51.@ResponseBody + ResponseEntity.md: -------------------------------------------------------------------------------- 1 | # @ResponseBody + ResponseEntity 2 | 3 | En Spring Boot, `@ResponseBody` y `ResponseEntity` son dos herramientas poderosas para gestionar las respuestas HTTP de los controladores y enviarlas a los clientes. Ambas permiten enviar datos en formato JSON, pero tienen diferencias significativas en cuanto a la flexibilidad y el control sobre la respuesta. 4 | 5 | ### 1. @ResponseBody 6 | 7 | `@ResponseBody` es una anotación que indica que el valor devuelto por un método de un controlador debe ser tratado directamente como el cuerpo de la respuesta HTTP. Esto permite enviar directamente objetos o listas de objetos en formato JSON al cliente sin tener que manipular encabezados, estados o configuraciones adicionales. 8 | 9 | #### Ejemplo Práctico 10 | 11 | Imaginemos que tienes una lista de clientes y quieres enviarla en respuesta a una solicitud HTTP GET. Al usar `@ResponseBody`, puedes definir un método en tu controlador para manejar esta solicitud y devolver los datos en JSON: 12 | 13 | ```java 14 | @GetMapping("/clientes") 15 | @ResponseBody 16 | public List traerClientes() { 17 | List clientes = clienteService.obtenerClientes(); 18 | return clientes; 19 | } 20 | ``` 21 | 22 | Aquí, al hacer una solicitud GET a `/clientes`, Spring serializa automáticamente la lista de `Cliente` en formato JSON y la coloca en el cuerpo de la respuesta HTTP. Esto es útil cuando deseas devolver datos simples y no necesitas manipular el estado HTTP o los encabezados de la respuesta. 23 | 24 | ### 2. ResponseEntity 25 | 26 | `ResponseEntity` es una clase de respuesta más avanzada y flexible que te permite gestionar todos los aspectos de una respuesta HTTP: el cuerpo, los encabezados y el código de estado. A diferencia de `@ResponseBody`, que solo permite devolver un cuerpo JSON, `ResponseEntity` facilita respuestas completamente personalizadas. 27 | 28 | #### Ejemplo Práctico 29 | 30 | Supongamos que, además de enviar la lista de clientes, quieres especificar un código de estado HTTP (como `200 OK`) y algunos encabezados personalizados. Puedes hacerlo usando `ResponseEntity`: 31 | 32 | ```java 33 | @GetMapping("/clientes") 34 | public ResponseEntity> traerClientes() { 35 | List clientes = clienteService.obtenerClientes(); 36 | if (clientes.isEmpty()) { 37 | return ResponseEntity.status(HttpStatus.NO_CONTENT).body(clientes); 38 | } 39 | return ResponseEntity.ok().body(clientes); 40 | } 41 | ``` 42 | 43 | En este ejemplo: 44 | 45 | - Si la lista de clientes está vacía, `ResponseEntity` permite devolver un estado `204 NO CONTENT` en lugar de `200 OK`, lo cual brinda mayor precisión. 46 | - Si hay clientes en la lista, la respuesta devuelve `200 OK` junto con los datos en JSON. 47 | 48 | #### Ventajas de ResponseEntity 49 | 50 | 1. **Control del Código de Estado:** Puedes devolver códigos de estado personalizados como `404 NOT FOUND` o `500 INTERNAL SERVER ERROR`, lo que facilita comunicar al cliente si la operación fue exitosa o si hubo errores. 51 | 52 | 2. **Encabezados Personalizados:** Puedes agregar encabezados HTTP como `Cache-Control` o `Content-Type` para controlar cómo el cliente debe manejar la respuesta. 53 | 54 | 3. **Cuerpo Personalizable:** Puedes incluir cualquier tipo de objeto en el cuerpo de la respuesta, lo que permite enviar datos de error o mensajes específicos, además de los datos solicitados. 55 | 56 | ### Resumen de Diferencias 57 | 58 | | Aspecto | @ResponseBody | ResponseEntity | 59 | |----------------------------|---------------------------------------------------------|----------------------------------------------------| 60 | | **Tipo** | Anotación | Clase | 61 | | **Cuerpo de Respuesta** | Envía directamente el cuerpo en JSON | Permite configurar el cuerpo junto con el estado y encabezados | 62 | | **Control de Estado HTTP** | No es posible modificar el estado (es siempre `200 OK`) | Permite personalizar el código de estado | 63 | | **Encabezados** | No se pueden personalizar | Permite añadir y modificar encabezados | 64 | 65 | ### ¿Cuándo Usar Cada Uno? 66 | 67 | - **`@ResponseBody`** es ideal para casos simples donde solo necesitas devolver datos JSON en respuesta a una solicitud GET, POST, etc., y no necesitas personalizar los encabezados ni los códigos de estado. 68 | 69 | - **`ResponseEntity`** es útil en casos más complejos donde se requiere control total sobre la respuesta HTTP, incluyendo la personalización del estado y de los encabezados. -------------------------------------------------------------------------------- /4.Spring Boot/55.Inversión de Control .md: -------------------------------------------------------------------------------- 1 | # Inversión de Control 2 | 3 | La Inversión de Control (IoC, por sus siglas en inglés) es un principio fundamental en el diseño de software, particularmente importante en frameworks como Spring. IoC representa un cambio en la forma en que el flujo de control en una aplicación es gestionado. Normalmente, en una aplicación tradicional, el programador escribe el código que controla directamente el flujo de la aplicación, llamando explícitamente a métodos y creando instancias de objetos cuando es necesario. Sin embargo, con IoC, este rol de control se invierte, y es el framework (como Spring) quien asume esta responsabilidad. 4 | 5 | ### ¿Cómo funciona IoC? 6 | 7 | En un flujo de trabajo tradicional: 8 | - La aplicación, mediante el código escrito por el programador, se encarga de invocar funcionalidades específicas de un framework o de otros módulos de la aplicación. 9 | - Esto significa que la aplicación está en control de todas las acciones y las llamadas de métodos ocurren cuando el programador las define en el código. 10 | 11 | Sin embargo, con IoC, el proceso se altera: 12 | - Ahora es el framework quien se encarga de llamar a la aplicación en los momentos adecuados, manejando el flujo en lugar del programador. La aplicación, en este caso, "cede" el control al framework. 13 | - Para que el framework pueda gestionar este flujo de manera efectiva, necesita saber cómo funciona la aplicación y qué elementos debe controlar. En Java, esta información generalmente se expresa mediante anotaciones (annotations) o archivos de configuración XML que indican cómo se deben manejar ciertos objetos o métodos. 14 | 15 | ### IoC y la creación de objetos 16 | 17 | Uno de los aspectos clave que IoC busca resolver es la creación innecesaria o repetitiva de objetos a través de la instrucción `new`, que genera una nueva instancia cada vez que es ejecutada. Sin IoC, el programador debe manejar manualmente la creación de instancias, lo que puede ser ineficiente o causar problemas si múltiples instancias de una misma clase son generadas cuando en realidad solo se necesita una. 18 | 19 | En el contexto de IoC: 20 | - Es el framework quien se encarga de crear, gestionar y suministrar las instancias de los objetos que la aplicación necesita, evitando la creación redundante de instancias. 21 | - Spring, por ejemplo, utiliza el patrón Singleton, creando solo una instancia de una clase específica, que luego está disponible para toda la aplicación. 22 | 23 | ### Inyección de Dependencias (DI) como mecanismo de IoC 24 | 25 | La Inversión de Control se implementa frecuentemente mediante un patrón llamado **Inyección de Dependencias** (Dependency Injection o DI), que permite que el framework maneje la creación de objetos y sus dependencias. 26 | - Con DI, el framework se encarga de “inyectar” los objetos que una clase necesita para funcionar, en lugar de que la clase misma los instancie. 27 | - Esto permite una mayor flexibilidad, modularidad y testabilidad en el código, ya que los componentes no dependen directamente de otros para ser instanciados. 28 | 29 | ### Ejemplo práctico 30 | 31 | Supongamos una clase `OrderService` que necesita una instancia de `PaymentService` para procesar los pagos de los pedidos. Sin IoC, el programador tendría que instanciar `PaymentService` directamente dentro de `OrderService` usando `new`. Esto crea una dependencia rígida y dificulta cambiar o probar diferentes implementaciones de `PaymentService`. 32 | 33 | Con IoC y DI, Spring crea y gestiona la instancia de `PaymentService` y luego la inyecta en `OrderService`. Así, `OrderService` no depende directamente de `PaymentService`, sino que depende de una interfaz o referencia que Spring provee. 34 | 35 | ### Beneficios de IoC 36 | 37 | 1. **Reducción de Dependencias Directas**: Las clases no dependen de otras clases específicas, lo que mejora la modularidad y facilita el cambio de implementaciones. 38 | 39 | 2. **Facilidad para Pruebas Unitarias**: Al desacoplar las dependencias, es más sencillo realizar pruebas unitarias, ya que es posible sustituir componentes reales por simulaciones o mocks. 40 | 41 | 3. **Modularidad y Reutilización**: Los componentes se vuelven más reutilizables y modulares al no estar rígidamente acoplados a otros. 42 | 43 | 4. **Menor Código de Configuración**: Gracias a IoC, el programador no necesita escribir el código de creación y gestión de instancias de objetos, ya que el framework maneja estas tareas. 44 | 45 | En conclusión, la Inversión de Control es un concepto poderoso que permite crear aplicaciones más modulares y fáciles de mantener. Es un aspecto clave de frameworks como Spring, que utilizan IoC para facilitar el desarrollo de aplicaciones de forma eficiente y escalable. -------------------------------------------------------------------------------- /4.Spring Boot/57.@Data.md: -------------------------------------------------------------------------------- 1 | # @Data 2 | 3 | Claro, aquí tienes una respuesta extensa y comprensiva sobre qué es la anotación `@Data` de Lombok en Java. Siéntete libre de agregar más información específica si lo necesitas. 4 | 5 | --- 6 | 7 | ### ¿Qué es `@Data` en Lombok? 8 | 9 | En el desarrollo con Java, la creación de clases de modelo o entidades a menudo implica escribir mucho código repetitivo, como métodos *getters*, *setters*, *toString()*, *equals()*, *hashCode()* y constructores. Para reducir este trabajo tedioso y mejorar la legibilidad del código, la biblioteca **Lombok** ofrece una solución práctica mediante anotaciones que generan automáticamente este código. 10 | 11 | Una de las anotaciones más utilizadas de Lombok es `@Data`. Esta anotación combina varias funcionalidades esenciales en una sola declaración, facilitando el manejo de clases que actúan como contenedores de datos (*data classes*). 12 | 13 | --- 14 | 15 | ### Funcionalidades de `@Data` 16 | 17 | Cuando se coloca la anotación `@Data` sobre una clase, Lombok genera automáticamente el siguiente código: 18 | 19 | 1. **Getters**: 20 | - Se crean métodos `get` para todas las propiedades de la clase. 21 | - Ejemplo: Para una propiedad `private String nombre;`, Lombok genera `public String getNombre() { return this.nombre; }`. 22 | 23 | 2. **Setters**: 24 | - Se generan métodos `set` para todas las propiedades de la clase que no sean finales. 25 | - Ejemplo: Para una propiedad `private int edad;`, Lombok genera `public void setEdad(int edad) { this.edad = edad; }`. 26 | 27 | 3. **Método `toString()`**: 28 | - Se genera un método que devuelve una representación en texto del objeto, incluyendo los valores de sus atributos. 29 | - Ejemplo de salida para un objeto: `Persona(nombre=Juan, edad=25)`. 30 | 31 | 4. **Método `equals()`**: 32 | - Se genera un método para comparar si dos objetos son iguales, basado en los valores de sus atributos. 33 | 34 | 5. **Método `hashCode()`**: 35 | - Se genera un código hash que representa el estado del objeto, utilizado en estructuras de datos como `HashMap`. 36 | 37 | 6. **Constructor requerido**: 38 | - Se genera un constructor que inicializa las propiedades finales (*final*) y aquellas marcadas con `@NonNull`. 39 | 40 | --- 41 | 42 | ### Ejemplo Práctico 43 | 44 | ```java 45 | import lombok.Data; 46 | 47 | @Data 48 | public class Persona { 49 | private String nombre; 50 | private int edad; 51 | private String email; 52 | } 53 | ``` 54 | 55 | **Sin Lombok**, tendríamos que escribir manualmente lo siguiente: 56 | 57 | ```java 58 | public class Persona { 59 | private String nombre; 60 | private int edad; 61 | private String email; 62 | 63 | // Getters 64 | public String getNombre() { 65 | return nombre; 66 | } 67 | 68 | public void setNombre(String nombre) { 69 | this.nombre = nombre; 70 | } 71 | 72 | public int getEdad() { 73 | return edad; 74 | } 75 | 76 | public void setEdad(int edad) { 77 | this.edad = edad; 78 | } 79 | 80 | public String getEmail() { 81 | return email; 82 | } 83 | 84 | public void setEmail(String email) { 85 | this.email = email; 86 | } 87 | 88 | // toString 89 | @Override 90 | public String toString() { 91 | return "Persona{" + 92 | "nombre='" + nombre + '\'' + 93 | ", edad=" + edad + 94 | ", email='" + email + '\'' + 95 | '}'; 96 | } 97 | 98 | // equals y hashCode 99 | @Override 100 | public boolean equals(Object o) { 101 | // Implementación manual 102 | } 103 | 104 | @Override 105 | public int hashCode() { 106 | // Implementación manual 107 | } 108 | } 109 | ``` 110 | 111 | Con `@Data`, ahorramos **decenas de líneas de código repetitivo**, mejorando la claridad y reduciendo errores humanos. 112 | 113 | --- 114 | 115 | ### Casos de Uso 116 | 117 | 1. **Clases de modelo o DTOs (Data Transfer Objects):** 118 | Son clases utilizadas para transportar datos entre diferentes capas de una aplicación. 119 | 120 | 2. **Entidades en frameworks como Hibernate o JPA:** 121 | Aunque hay que tener cuidado al usar setters indiscriminados en entidades gestionadas por frameworks ORM. 122 | 123 | 3. **Pruebas unitarias:** 124 | Facilita la creación de objetos de prueba sin necesidad de implementar todos los métodos manualmente. 125 | 126 | --- 127 | 128 | ### Limitaciones y Cuidados 129 | 130 | 1. **Compatibilidad con frameworks ORM como JPA:** 131 | En entidades, a menudo necesitas personalizar los métodos generados por Lombok. Por ejemplo, podrías requerir que el método `toString()` excluya ciertas relaciones bidireccionales para evitar referencias circulares. 132 | 133 | 2. **Impacto en la depuración:** 134 | Dado que el código generado no es visible en el archivo fuente, puede ser más difícil de depurar si no estás familiarizado con Lombok. 135 | 136 | 3. **Incompatibilidades:** 137 | Algunas herramientas, como ciertos analizadores estáticos, pueden no interpretar correctamente el código generado. 138 | 139 | 4. **Sobreescritura de métodos:** 140 | Si necesitas implementar un método personalizado, debes asegurarte de que no entre en conflicto con los generados automáticamente. 141 | 142 | --- 143 | 144 | ### Alternativas 145 | 146 | Si no deseas usar Lombok, puedes emplear las herramientas de generación de código de tu IDE (como IntelliJ IDEA o Eclipse) o librerías más específicas, aunque estas alternativas no ofrecen la misma automatización ni la limpieza que proporciona Lombok. 147 | 148 | --- 149 | 150 | En conclusión, `@Data` es una herramienta poderosa para reducir la verbosidad en Java, especialmente útil en clases de modelo. Sin embargo, como con cualquier herramienta, su uso debe evaluarse cuidadosamente según las necesidades del proyecto. -------------------------------------------------------------------------------- /4.Spring Boot/58.Hibernate.md: -------------------------------------------------------------------------------- 1 | # Hibernate 2 | 3 | #### **¿Qué es Hibernate?** 4 | Hibernate es una implementación de JPA (Java Persistence API), que actúa como un framework de mapeo objeto-relacional (ORM, por sus siglas en inglés). Este framework permite a los desarrolladores interactuar con bases de datos utilizando objetos de Java, eliminando gran parte de la necesidad de escribir consultas SQL explícitas. 5 | 6 | El principal objetivo de Hibernate es proporcionar una forma sencilla y eficiente de mapear las clases de un modelo de datos en Java a tablas de una base de datos relacional. Además de su capacidad de mapeo, Hibernate gestiona automáticamente las transacciones, conexiones y consultas, simplificando el desarrollo. 7 | 8 | #### **Relación entre Hibernate y JPA** 9 | JPA es una especificación que define cómo deben ser los frameworks de persistencia en Java, mientras que Hibernate es una implementación concreta de esta especificación. Esto significa que, al utilizar Hibernate, se pueden aplicar las directrices y estándares de JPA, garantizando la interoperabilidad y el cumplimiento de buenas prácticas. 10 | 11 | --- 12 | 13 | ### **Conceptos clave en Hibernate** 14 | Hibernate utiliza una serie de **annotations** para realizar el mapeo de clases a tablas y atributos a columnas. A continuación, se detalla cada una de las más importantes: 15 | 16 | #### **1. Annotations para el mapeo básico** 17 | - **`@Entity`:** 18 | - Declara que una clase es una entidad que se mapeará a una tabla en la base de datos. 19 | - Ejemplo: 20 | ```java 21 | @Entity 22 | public class Producto { 23 | // atributos y métodos 24 | } 25 | ``` 26 | - **`@Table`:** 27 | - Permite especificar el nombre de la tabla que se asignará a una clase. 28 | - Si no se usa, el nombre de la clase se toma como nombre de la tabla. 29 | - Ejemplo: 30 | ```java 31 | @Entity 32 | @Table(name = "productos") 33 | public class Producto { 34 | // atributos y métodos 35 | } 36 | ``` 37 | 38 | #### **2. Annotations para la clave primaria** 39 | - **`@Id`:** 40 | - Marca un atributo como la clave primaria de la tabla. 41 | - Ejemplo: 42 | ```java 43 | @Id 44 | private Long id; 45 | ``` 46 | - **`@GeneratedValue`:** 47 | - Indica cómo se generará el valor de la clave primaria. Estrategias comunes: 48 | - `AUTO`: Hibernate elige la estrategia adecuada. 49 | - `IDENTITY`: Usada para claves autoincrementales. 50 | - `SEQUENCE`: Genera valores usando secuencias. 51 | - `TABLE`: Usa una tabla específica para gestionar claves primarias. 52 | - Ejemplo: 53 | ```java 54 | @Id 55 | @GeneratedValue(strategy = GenerationType.IDENTITY) 56 | private Long id; 57 | ``` 58 | 59 | #### **3. Annotations para columnas** 60 | - **`@Column`:** 61 | - Mapea un atributo de una clase a una columna específica en la tabla. 62 | - Si no se utiliza, Hibernate toma el nombre del atributo como el nombre de la columna. 63 | - Ejemplo: 64 | ```java 65 | @Column(name = "nombre_producto", nullable = false, length = 100) 66 | private String nombre; 67 | ``` 68 | 69 | #### **4. Relaciones entre entidades** 70 | Hibernate permite modelar relaciones entre clases que se traducen en relaciones entre tablas en la base de datos: 71 | - **`@OneToOne`:** Relación uno a uno. 72 | - **`@OneToMany`:** Relación uno a muchos. 73 | - **`@ManyToOne`:** Relación muchos a uno. 74 | - **`@ManyToMany`:** Relación muchos a muchos. 75 | 76 | - **`@JoinColumn`:** 77 | - Especifica la columna que actuará como clave foránea para la relación. 78 | - Ejemplo: 79 | ```java 80 | @OneToMany 81 | @JoinColumn(name = "categoria_id") 82 | private List productos; 83 | ``` 84 | 85 | --- 86 | 87 | ### **Ventajas de Hibernate** 88 | 1. **Abstracción del SQL:** 89 | - Los desarrolladores trabajan principalmente con objetos en Java y Hibernate se encarga de traducir esas operaciones a SQL. 90 | 91 | 2. **Independencia de la base de datos:** 92 | - Hibernate puede trabajar con diferentes bases de datos (MySQL, PostgreSQL, Oracle, etc.) sin necesidad de modificar el código. 93 | 94 | 3. **Optimización:** 95 | - Soporte para técnicas avanzadas como *caching* y *lazy loading* (carga diferida de datos). 96 | 97 | 4. **Gestión automática de transacciones:** 98 | - Hibernate simplifica la gestión de transacciones y conexiones, mejorando la productividad del desarrollador. 99 | 100 | --- 101 | 102 | ### **Lenguaje de consultas de Hibernate (HQL)** 103 | Hibernate incluye un lenguaje específico llamado **HQL (Hibernate Query Language)**, que permite realizar consultas utilizando nombres de clases y atributos en lugar de nombres de tablas y columnas. Aunque este curso no se centra en HQL, es importante saber que está disponible y proporciona una forma poderosa de interactuar con la base de datos. 104 | 105 | --- 106 | 107 | ### **Conclusiones** 108 | Hibernate es una herramienta poderosa y flexible para la persistencia de datos en aplicaciones Java. Aunque puede ser compleja debido a la cantidad de annotations y configuraciones posibles, su aprendizaje y uso proporcionan una base sólida para construir aplicaciones robustas y escalables. Una vez configurado correctamente, Hibernate elimina muchas tareas repetitivas, permitiendo a los desarrolladores centrarse en la lógica del negocio. -------------------------------------------------------------------------------- /4.Spring Boot/59.Relaciones @OneToOne, @OneToMany y @ManyToMany.md: -------------------------------------------------------------------------------- 1 | # Relaciones con JPA + Hibernate: @OneToOne, @OneToMany y @ManyToMany 2 | 3 | La gestión de relaciones entre entidades es uno de los aspectos fundamentales al trabajar con JPA (Java Persistence API) y Hibernate, ya que permite mapear las relaciones entre clases en Java a las relaciones entre tablas en una base de datos relacional. Estas relaciones se definen usando anotaciones como `@OneToOne`, `@OneToMany` y `@ManyToMany`, y son esenciales para mantener la lógica y estructura de datos en sincronía con el modelo relacional. 4 | 5 | --- 6 | 7 | #### **Relaciones 1 a 1 (@OneToOne)** 8 | 9 | La anotación `@OneToOne` se utiliza para definir una relación donde una entidad está asociada a una sola instancia de otra entidad. A nivel de base de datos, esto se traduce en una clave foránea (FK) que conecta ambas tablas. 10 | 11 | **Ejemplo: Auto y Propietario** 12 | - Un Auto tiene un único Propietario. 13 | - Esto se representa con un objeto del tipo `Propietario` en la clase `Auto`. 14 | 15 | **Implementación en código:** 16 | ```java 17 | @Entity 18 | public class Auto { 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | @OneToOne 24 | @JoinColumn(name = "id_propietario", referencedColumnName = "id") 25 | private Propietario propietario; 26 | } 27 | ``` 28 | 29 | **Notas importantes:** 30 | - La anotación `@JoinColumn` se usa para especificar el nombre de la FK en la tabla correspondiente. 31 | - La relación puede ser unidireccional (una entidad conoce a la otra) o bidireccional (ambas entidades se conocen mutuamente). 32 | - En una relación bidireccional, la otra clase también incluiría un atributo que representa la relación, decorado con `@OneToOne` y posiblemente con el atributo `mappedBy`. 33 | 34 | --- 35 | 36 | #### **Relaciones 1 a Muchos y Muchos a 1 (@OneToMany y @ManyToOne)** 37 | 38 | Estas anotaciones definen relaciones donde una entidad está asociada con múltiples instancias de otra entidad. 39 | 40 | **Ejemplo: Auto y Propietarios** 41 | - Un Auto puede tener varios Propietarios a lo largo del tiempo. 42 | - Esto se representa con una colección en la clase `Auto`. 43 | 44 | **Implementación en código:** 45 | ```java 46 | @Entity 47 | public class Auto { 48 | @Id 49 | @GeneratedValue(strategy = GenerationType.IDENTITY) 50 | private Long id; 51 | 52 | @OneToMany(mappedBy = "auto") 53 | private List propietarios; 54 | } 55 | 56 | @Entity 57 | public class Propietario { 58 | @Id 59 | @GeneratedValue(strategy = GenerationType.IDENTITY) 60 | private Long id; 61 | 62 | @ManyToOne 63 | @JoinColumn(name = "id_auto") 64 | private Auto auto; 65 | } 66 | ``` 67 | 68 | **Notas importantes:** 69 | - En una relación unidireccional, solo sería necesario mapear `@OneToMany` en `Auto`. 70 | - Para relaciones bidireccionales, el atributo `mappedBy` se usa en `@OneToMany` para indicar que la relación está definida en la otra clase (`Propietario` en este caso). 71 | - Hibernate prefiere las relaciones bidireccionales por coherencia y control de datos. 72 | 73 | --- 74 | 75 | #### **Relaciones Muchos a Muchos (@ManyToMany)** 76 | 77 | La anotación `@ManyToMany` se utiliza para modelar relaciones donde múltiples instancias de una entidad pueden estar asociadas con múltiples instancias de otra entidad. A nivel de base de datos, esto requiere una tabla intermedia para representar la relación. 78 | 79 | **Ejemplo: Autos y Conductores** 80 | - Un Auto puede ser conducido por varios Conductores, y un Conductor puede manejar varios Autos. 81 | 82 | **Implementación en código:** 83 | ```java 84 | @Entity 85 | public class Auto { 86 | @Id 87 | @GeneratedValue(strategy = GenerationType.IDENTITY) 88 | private Long id; 89 | 90 | @ManyToMany 91 | @JoinTable( 92 | name = "rel_auto_conductor", 93 | joinColumns = @JoinColumn(name = "auto_id"), 94 | inverseJoinColumns = @JoinColumn(name = "conductor_id") 95 | ) 96 | private List conductores; 97 | } 98 | 99 | @Entity 100 | public class Conductor { 101 | @Id 102 | @GeneratedValue(strategy = GenerationType.IDENTITY) 103 | private Long id; 104 | 105 | @ManyToMany(mappedBy = "conductores") 106 | private List autos; 107 | } 108 | ``` 109 | 110 | **Notas importantes:** 111 | - La anotación `@JoinTable` permite personalizar el nombre de la tabla intermedia y las columnas de FK. 112 | - Si no se especifica `@JoinTable`, JPA generará una tabla intermedia con un nombre predeterminado. 113 | - Las relaciones `@ManyToMany` suelen ser bidireccionales, pero también pueden ser unidireccionales. 114 | 115 | --- 116 | 117 | ### Conceptos Clave 118 | 119 | 1. **Unidireccional vs. Bidireccional**: 120 | - En relaciones unidireccionales, solo una entidad conoce la relación. 121 | - En bidireccionales, ambas entidades conocen la relación. 122 | 123 | 2. **Tabla intermedia**: 124 | - En relaciones `@ManyToMany`, JPA crea automáticamente una tabla intermedia que conecta las dos entidades. 125 | 126 | 3. **Parámetro `mappedBy`**: 127 | - Define qué lado de la relación es el dueño (controla la FK en la base de datos). 128 | 129 | 4. **Sincronización con la base de datos**: 130 | - Durante el desarrollo, es importante reiniciar la base de datos cuando se cambian relaciones para evitar conflictos en la estructura. 131 | 132 | --- 133 | 134 | ### Conclusión 135 | 136 | El mapeo de relaciones con `@OneToOne`, `@OneToMany`, `@ManyToOne`, y `@ManyToMany` en JPA + Hibernate es una herramienta poderosa para gestionar datos relacionales en aplicaciones Java. Estas anotaciones simplifican el trabajo con bases de datos al permitir que el modelo lógico en código se sincronice automáticamente con el modelo físico en la base de datos. -------------------------------------------------------------------------------- /5.Spring Security/60.Autenticación vs Autorización.md: -------------------------------------------------------------------------------- 1 | # Autenticación vs. Autorización 2 | 3 | ### **Autenticación vs. Autorización: Entendiendo las Diferencias y su Importancia en Seguridad Informática** 4 | 5 | En el ámbito de la seguridad informática, **autenticación** y **autorización** son dos conceptos clave que trabajan de manera conjunta para proteger sistemas, datos y recursos sensibles. Aunque a menudo se mencionan juntos, cada uno tiene un propósito único dentro de un sistema de seguridad. Comprender sus diferencias y cómo se relacionan es crucial para implementar mecanismos de protección efectivos. 6 | 7 | --- 8 | 9 | ### **¿Qué es la Autenticación?** 10 | 11 | La autenticación es el proceso que responde a la pregunta **«¿Eres quien dices ser?»**. Se centra en **verificar la identidad** de una persona, dispositivo o entidad antes de permitirles acceder a un sistema. 12 | 13 | - **Métodos comunes de autenticación:** 14 | - **Credenciales tradicionales:** Un nombre de usuario y contraseña. 15 | - **Autenticación multifactorial (MFA):** Combina varios factores como: 16 | - Algo que el usuario sabe (contraseña). 17 | - Algo que el usuario tiene (un código enviado al celular). 18 | - Algo que el usuario es (huellas dactilares o reconocimiento facial). 19 | - **Biometría:** Reconocimiento facial, de iris, huellas dactilares, o incluso patrones de voz. 20 | - **Autenticación basada en tokens:** Uso de dispositivos físicos o software como generadores de claves únicas. 21 | 22 | La autenticación actúa como la **primera línea de defensa** en un sistema, validando que quien intenta acceder sea realmente quien afirma ser. Sin una autenticación sólida, se abre la puerta a ataques como el acceso no autorizado, robo de identidad o explotación de cuentas vulnerables. 23 | 24 | #### Ejemplo: 25 | 26 | Cuando inicias sesión en tu correo electrónico con tu usuario y contraseña, estás pasando por el proceso de autenticación. 27 | 28 | --- 29 | 30 | ### **¿Qué es la Autorización?** 31 | 32 | Una vez que el sistema ha verificado quién eres mediante la autenticación, la autorización entra en juego. La autorización se ocupa de responder a la pregunta: **«¿Qué estás autorizado a hacer?»**. 33 | 34 | - **Enfoque principal:** La autorización determina los **niveles de acceso** y las **acciones permitidas** para un usuario dentro del sistema. 35 | - **Implementación:** A menudo se gestiona a través de: 36 | - Roles asignados (por ejemplo, _administrador_, _usuario_, _invitado_). 37 | - Políticas de acceso específicas. 38 | - Permisos detallados sobre recursos individuales. 39 | 40 | La autorización no puede realizarse sin autenticación previa, ya que depende de la identidad confirmada del usuario para tomar decisiones de acceso. 41 | 42 | #### Ejemplo: 43 | 44 | Aunque un empleado puede iniciar sesión en el sistema de una empresa (autenticación exitosa), es posible que solo tenga permisos para ver su perfil personal y no para acceder a información de recursos humanos o bases de datos confidenciales. 45 | 46 | --- 47 | 48 | ### **Relación y Diferencias Clave entre Autenticación y Autorización** 49 | 50 | #### **Relación:** 51 | 52 | - La **autenticación** es el paso inicial: identifica quién es el usuario. 53 | - La **autorización** viene después: define qué acciones puede realizar el usuario autenticado. 54 | 55 | #### **Diferencias:** 56 | 57 | | Aspecto | Autenticación | Autorización | 58 | | ------------------------- | ------------------------------------------------ | ---------------------------------------------- | 59 | | **¿Qué valida?** | La identidad del usuario. | Los permisos y niveles de acceso del usuario. | 60 | | **Pregunta clave** | «¿Eres quien dices ser?» | «¿Qué puedes hacer?» | 61 | | **Se realiza cuándo** | Antes de permitir el acceso al sistema. | Después de verificar la identidad del usuario. | 62 | | **Proceso independiente** | Puede implementarse sin autorización. | Depende de la autenticación previa. | 63 | | **Ejemplo práctico** | Ingresar con usuario y contraseña en un sistema. | Restringir acceso a funciones administrativas. | 64 | 65 | --- 66 | 67 | ### **Importancia de Integrar Ambos Conceptos** 68 | 69 | Una implementación robusta de seguridad informática requiere tanto autenticación como autorización. Juntos, estos procesos garantizan que: 70 | 71 | 1. **Solo usuarios legítimos accedan al sistema:** Reduciendo el riesgo de accesos no autorizados. 72 | 2. **Los usuarios accedan solo a lo que les corresponde:** Limitando posibles errores, mal uso de recursos o exposición innecesaria de datos sensibles. 73 | 74 | #### **Escenarios Comunes:** 75 | 76 | - **Banca en línea:** 77 | - Autenticación: Ingresar con usuario, contraseña y un código SMS. 78 | - Autorización: Solo puedes ver tu cuenta y transferir fondos hasta un límite, a menos que seas administrador del sistema. 79 | - **Aplicaciones corporativas:** 80 | - Autenticación: El sistema valida a cada empleado mediante credenciales únicas. 81 | - Autorización: Los permisos varían según el rol, como acceso a documentos privados o permisos de edición. 82 | 83 | --- 84 | 85 | ### **Conclusión** 86 | 87 | Aunque la autenticación y la autorización están estrechamente relacionadas, cumplen funciones diferentes pero complementarias en la seguridad de los sistemas. La autenticación garantiza que el usuario es quien dice ser, mientras que la autorización regula lo que ese usuario puede hacer dentro del sistema. Al integrarlos de manera efectiva, las organizaciones pueden construir barreras de seguridad sólidas, reduciendo el riesgo de accesos no autorizados y protegiendo sus recursos más valiosos. 88 | -------------------------------------------------------------------------------- /5.Spring Security/61.Stateful vs Stateless.md: -------------------------------------------------------------------------------- 1 | # Stateful vs Stateless 2 | 3 | El concepto de **Stateful vs Stateless** en informática se refiere a cómo una aplicación gestiona y almacena el estado de las interacciones de los usuarios. Es una distinción clave para entender el diseño de sistemas eficientes, escalables y seguros en el desarrollo de aplicaciones web, servicios en la nube y arquitecturas distribuidas. A continuación, exploraremos ambos conceptos en detalle: 4 | 5 | --- 6 | 7 | ### **Aplicaciones Stateful** 8 | 9 | **Stateful** significa que la aplicación **mantiene el estado** o contexto de la interacción del usuario entre solicitudes. Esto implica que, tras una autenticación o acción inicial, el servidor conserva información sobre el usuario y su sesión. 10 | 11 | #### **Características Principales de las Aplicaciones Stateful** 12 | 13 | 1. **Persistencia de Estado:** 14 | - La información sobre la sesión del usuario (como su identidad, preferencias, historial de navegación o permisos) se almacena en el servidor. 15 | - Esto puede realizarse en la memoria del servidor o en una base de datos. 16 | 2. **Gestión de Sesiones:** 17 | - Utilizan **cookies**, **sesiones** o tokens únicos asociados con el servidor para identificar y gestionar el estado del usuario. 18 | - Ejemplo: Una aplicación de banca en línea mantiene tu sesión activa mientras navegas por diferentes secciones, sin necesidad de reautenticación. 19 | 3. **Escalabilidad Limitada:** 20 | - Dado que el servidor debe almacenar información para cada usuario, escalar horizontalmente (añadiendo más servidores) es más complejo. 21 | - Requiere mecanismos como replicación o almacenamiento compartido para garantizar que todas las instancias del servidor tengan acceso al mismo estado. 22 | 4. **Complejidad:** 23 | - La gestión del estado añade un nivel de complejidad al desarrollo, especialmente en entornos distribuidos, ya que la sincronización del estado entre servidores debe manejarse cuidadosamente. 24 | 5. **Seguridad:** 25 | - Aunque las sesiones son útiles, si no se gestionan adecuadamente, pueden ser vulnerables a ataques como **hijacking de sesiones**, **CSRF** o **manipulación de cookies**. 26 | 27 | #### **Ventajas de Aplicaciones Stateful** 28 | 29 | - Permiten una experiencia de usuario fluida y personalizada, con interacciones más contextuales. 30 | - Son ideales para aplicaciones que dependen de un historial o un contexto persistente, como aplicaciones bancarias o plataformas de gestión empresarial. 31 | 32 | #### **Desventajas de Aplicaciones Stateful** 33 | 34 | - Son más difíciles de escalar y mantener, especialmente en arquitecturas distribuidas. 35 | - Requieren más recursos para almacenar y gestionar el estado de múltiples usuarios. 36 | 37 | --- 38 | 39 | ### **Aplicaciones Stateless** 40 | 41 | Las aplicaciones **Stateless** procesan cada solicitud del usuario como una transacción completamente independiente, sin depender de ninguna información sobre interacciones previas. Esto significa que no mantienen un estado continuo entre las solicitudes. 42 | 43 | #### **Características Principales de las Aplicaciones Stateless** 44 | 45 | 1. **Ausencia de Persistencia de Estado:** 46 | - El servidor no almacena información sobre el usuario entre solicitudes. 47 | - Toda la información necesaria para procesar una solicitud se incluye en esa solicitud, como un **token de autenticación**. 48 | 2. **Autenticación Basada en Tokens:** 49 | - Una vez autenticado, el cliente recibe un token (por ejemplo, un **JWT**) que contiene información como identidad y permisos. 50 | - Este token se envía con cada solicitud, permitiendo al servidor procesarla sin depender de datos previamente almacenados. 51 | 3. **Escalabilidad Mejorada:** 52 | - Las aplicaciones Stateless son ideales para arquitecturas en la nube y sistemas distribuidos, ya que cualquier instancia del servidor puede manejar cualquier solicitud. 53 | - Esto simplifica la implementación de balanceadores de carga y otras estrategias de escalado. 54 | 4. **Simplicidad:** 55 | - El diseño es más sencillo porque no hay necesidad de gestionar estados de usuario entre solicitudes. 56 | 5. **Menor Uso de Recursos:** 57 | - Al no almacenar información de sesión, se reducen los requerimientos de memoria y procesamiento en el servidor. 58 | 59 | #### **Ventajas de Aplicaciones Stateless** 60 | 61 | - Escalabilidad y distribución más sencilla, ideales para sistemas con alta demanda. 62 | - Menor complejidad en la arquitectura y mantenimiento. 63 | - Compatible con sistemas modernos como **microservicios** y **API REST**. 64 | 65 | #### **Desventajas de Aplicaciones Stateless** 66 | 67 | - Las interacciones no son tan contextuales, lo que puede afectar la experiencia del usuario. 68 | - Algunas operaciones complejas requieren implementar métodos adicionales para manejar el contexto, como el almacenamiento en el cliente. 69 | 70 | --- 71 | 72 | ### **Comparativa entre Stateful y Stateless** 73 | 74 | | **Característica** | **Stateful** | **Stateless** | 75 | | -------------------------- | ---------------------------------------------- | --------------------------------------------------- | 76 | | **Persistencia de Estado** | Sí, se mantiene en el servidor. | No, cada solicitud es independiente. | 77 | | **Gestión de Sesiones** | Cookies o sesiones almacenadas en el servidor. | Tokens enviados con cada solicitud. | 78 | | **Escalabilidad** | Difícil de escalar horizontalmente. | Fácil de escalar horizontalmente. | 79 | | **Uso de Recursos** | Mayor, debido al almacenamiento de sesiones. | Menor, ya que no se guarda estado. | 80 | | **Complejidad** | Más complejo de implementar y mantener. | Más sencillo y fácil de mantener. | 81 | | **Aplicaciones Comunes** | Plataformas bancarias, CRM. | APIs REST, aplicaciones en la nube, microservicios. | 82 | 83 | --- 84 | 85 | ### **¿Cuál elegir?** 86 | 87 | - **Stateful:** Si tu aplicación necesita un contexto persistente y personalizado, como en sistemas bancarios o donde el historial del usuario es crucial. 88 | - **Stateless:** Si buscas escalabilidad, simplicidad y una arquitectura adecuada para servicios distribuidos o basados en la nube. 89 | 90 | Ambos enfoques tienen sus beneficios y limitaciones, y la elección depende del caso de uso específico y los requisitos del sistema. 91 | -------------------------------------------------------------------------------- /5.Spring Security/62. Roles y Permisos.md: -------------------------------------------------------------------------------- 1 | # Roles y Permisos 2 | 3 | ### ¿Qué son los roles y permisos? 4 | 5 | En el ámbito de la **seguridad informática**, los **roles** y **permisos** son conceptos fundamentales para gestionar y controlar el acceso a los recursos de un sistema. Estos términos permiten estructurar la interacción de los usuarios con un sistema, determinando quién puede acceder a qué recursos y qué acciones pueden realizar sobre ellos. Esto es especialmente importante para proteger la información, garantizar la integridad de los datos y facilitar la administración en sistemas pequeños o grandes. 6 | 7 | --- 8 | 9 | ### **Roles** 10 | Un **rol** es una agrupación de permisos que se asigna a uno o varios usuarios. Los roles se utilizan para simplificar la administración del acceso: en lugar de gestionar permisos individualmente, se agrupan en un rol y se asignan a usuarios o grupos según sus necesidades. Los roles son altamente personalizables según el contexto del sistema. 11 | 12 | #### **Ejemplos de roles comunes:** 13 | 1. **Administrador:** 14 | - Permisos: Crear, leer, actualizar y eliminar cualquier recurso. 15 | - Función: Tiene control total del sistema, incluyendo la administración de usuarios. 16 | 17 | 2. **Usuario estándar:** 18 | - Permisos: Leer información, modificar su propia información y realizar ciertas tareas según su asignación. 19 | - Función: Acceso limitado, generalmente relacionado con sus propias actividades en el sistema. 20 | 21 | 3. **Invitado:** 22 | - Permisos: Solo lectura en recursos específicos, como datos públicos. 23 | - Función: Acceso muy restringido para usuarios temporales o externos. 24 | 25 | #### **Ventajas del uso de roles:** 26 | - **Eficiencia:** Facilita la administración del acceso al asignar un conjunto de permisos de una sola vez. 27 | - **Escalabilidad:** Adecuado para sistemas con muchos usuarios. 28 | - **Flexibilidad:** Se pueden crear roles personalizados para adaptarse a las necesidades del sistema. 29 | 30 | --- 31 | 32 | ### **Permisos** 33 | Los **permisos** son las reglas específicas que definen qué acciones puede realizar un usuario sobre un recurso determinado. Mientras que los roles agrupan permisos, los permisos son las unidades básicas que definen las capacidades de acceso. 34 | 35 | #### **Ejemplos de permisos comunes:** 36 | 1. **Lectura (Read):** Permite acceder y visualizar datos. 37 | - Ejemplo: Consultar un informe o revisar un archivo. 38 | 39 | 2. **Escritura (Write):** Permite crear o modificar datos. 40 | - Ejemplo: Actualizar un perfil o agregar un nuevo registro. 41 | 42 | 3. **Eliminación (Delete):** Permite borrar datos. 43 | - Ejemplo: Eliminar un archivo o un registro en la base de datos. 44 | 45 | 4. **Ejecución (Execute):** Permite realizar acciones específicas como ejecutar programas o procesos. 46 | - Ejemplo: Ejecutar un script o iniciar un servicio. 47 | 48 | #### **Importancia de los permisos:** 49 | - Determinan las acciones que los usuarios pueden realizar, asegurando que solo tengan acceso a lo necesario para su rol. 50 | - Pueden asignarse individualmente o como parte de un rol para mayor flexibilidad. 51 | 52 | --- 53 | 54 | ### **Ejemplo práctico: Sistema de gestión de proyectos** 55 | En un sistema como Jira o Trello, los roles y permisos pueden definirse de la siguiente manera: 56 | - **Administrador de proyectos:** Puede crear y eliminar proyectos, asignar tareas y acceder a todos los informes. 57 | - **Miembro del equipo:** Puede visualizar proyectos, actualizar tareas asignadas y comentar en discusiones. 58 | - **Cliente:** Solo puede visualizar el progreso y proporcionar retroalimentación. 59 | 60 | Este enfoque asegura que cada usuario tenga acceso únicamente a las funciones necesarias para cumplir con sus responsabilidades. 61 | 62 | --- 63 | 64 | ### **Importancia de los roles y permisos en la seguridad informática** 65 | 1. **Prevención del acceso no autorizado:** Limita el acceso a datos y recursos sensibles únicamente a los usuarios autorizados. 66 | 2. **Facilidad de administración:** Los roles reducen la complejidad al permitir la asignación masiva de permisos. 67 | 3. **Cumplimiento normativo:** Ayuda a cumplir con políticas internas y regulaciones legales, facilitando auditorías y controles de seguridad. 68 | 4. **Minimización de riesgos:** Un acceso bien gestionado reduce las posibilidades de errores humanos o violaciones de seguridad. 69 | 70 | --- 71 | 72 | ### **Modelos de control de acceso** 73 | La implementación de roles y permisos se gestiona mediante **modelos de control de acceso**, que definen cómo se asignan y gestionan las autorizaciones. Algunos de los modelos más comunes son: 74 | 75 | 1. **Control de Acceso Basado en Roles (RBAC):** 76 | - Asigna permisos a roles, y los roles a usuarios. 77 | - Ejemplo: Un rol "Contador" podría tener permisos para ver y editar facturas. 78 | 79 | 2. **Control de Acceso Basado en Atributos (ABAC):** 80 | - Utiliza atributos como departamento, puesto o ubicación para definir el acceso. 81 | - Ejemplo: Un empleado del área de Recursos Humanos puede acceder solo a información relacionada con ese departamento. 82 | 83 | 3. **Control de Acceso Discrecional (DAC):** 84 | - El propietario del recurso decide quién tiene acceso. 85 | - Ejemplo: Un archivo puede ser compartido por su creador con otros usuarios específicos. 86 | 87 | 4. **Control de Acceso Obligatorio (MAC):** 88 | - Utiliza una política centralizada y niveles de seguridad para controlar el acceso. 89 | - Ejemplo: Documentos clasificados accesibles solo para usuarios con la autorización adecuada. 90 | 91 | --- 92 | 93 | ### **Conclusión** 94 | Los roles y permisos son esenciales para garantizar la seguridad, eficiencia y escalabilidad de un sistema informático. Al implementar un sistema robusto de control de acceso, las organizaciones pueden proteger sus recursos, facilitar la administración y cumplir con regulaciones de seguridad. Su personalización y correcta configuración son clave para el éxito en cualquier entorno tecnológico. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Repositorio para Aprender el Camino a Ser un Buen Desarrollador Backend 2 | Este repositorio irá guardando contenido según lo vaya aprendiendo en mi camino como especialista backend, en mi caso con Java y Spring. 3 | 4 | La idea surge gracias al [#Challenge-gentleman-diferencia](https://www.youtube.com/watch?v=T1bTgsYjkYw&t) de Gentleman Programming y tratará sobre crear contenido en LinkedIn y GitHub que sirva como autoaprendizaje y enseñanza para mejorar y diferenciarme de los demás desarrolladores backend. 5 | 6 | ![Gif de un Hello world!](https://www.iiserkol.ac.in/~cds/assets/image/intro_to_comp_programming.jpg) 7 | 8 | ## Contenido 9 | - **Tema 1: Internet.** 10 | - [¿Cómo funciona Internet?](1.%20Internet/1.Cómo%20funciona%20Internet.md) 11 | - [¿Qué es HTTP?](1.%20Internet/2.Qué%20es%20HTTP.md) 12 | - [La diferencia entre HTTP y HTTPS](1.%20Internet/3.La%20diferencia%20entre%20HTTP%20y%20HTTPS.md) 13 | - [Métodos HTTP (Usando Java)](1.%20Internet/4.Métodos%20HTTP%20(Usando%20Java).md) 14 | - [¿Qué es un nombre de dominio?](1.%20Internet/5.Qué%20es%20un%20nombre%20de%20dominio) 15 | - [¿Qué es el Hosting?](1.%20Internet/6.Qué%20es%20el%20Hosting.md) 16 | - [Cómo funcionan los navegadores](1.%20Internet/7.Cómo%20funcionan%20los%20navegadores.md) 17 | 18 | - **Tema 2: Java.** 19 | - [¿Que es java?](2.Java/1.Que%20es%20java.md) 20 | - [Tipos de datos y variables en java](2.Java/2.Tipos%20de%20datos%20y%20variables%20en%20java.md) 21 | - [Condicionales simples y multiples](2.Java/3.Condicionales%20simples%20y%20multiples.md) 22 | - [Condicional Switch](2.Java/4.Condicional%20Switch.md) 23 | - [Bucle While](2.Java/5.Bucle%20While.md) 24 | - [Bucles For](2.Java/6.Bucles%20For.md) 25 | - [Vectores (Arrays)](2.Java/7.Vectores%20(Arrays).md) 26 | - [Matrices](2.Java/8.Matrices.md) 27 | - [Funciones](2.Java/9.Funciones.md) 28 | - [Fechas y horas](2.Java/10.Fechas%20y%20horas.md) 29 | 30 | - **Tema 3: Java POO.** 31 | - [POO Programación Orientada a Objetos](3.Java%20POO/11.POO%20Programación%20Orientada%20a%20Objetos.md) 32 | - [Que son las clases y como crearla](3.Java%20POO/12.Que%20son%20las%20clases%20y%20como%20crearla.md) 33 | - [Metodos y como crearlos](3.Java%20POO/13.Metodos%20y%20como%20crearlos.md) 34 | - [Métodos Constructores y Objetos En Java](3.Java%20POO/14.Métodos%20Constructores%20y%20Objetos%20En%20Java.md) 35 | - [Getters y Setters en java](3.Java%20POO/15.Getters%20y%20Setters%20en%20java.md) 36 | - [Herencia en Java](3.Java%20POO/16.Herencia%20en%20Java.md) 37 | - [Polimorfismo en java](3.Java%20POO/17.Polimorfismo%20en%20java.md) 38 | - [Encapsulamiento en Java](3.Java%20POO/18.Encapsulamiento%20en%20Java.md) 39 | - [Clases Abstractas](3.Java%20POO/19.Clases%20Abstractas.md) 40 | - [Interfaces en Java](3.Java%20POO/20.Interfaces%20en%20Java.md) 41 | - [Collections en Java](3.Java%20POO/21.Collections%20en%20Java.md) 42 | - [ArrayList en Java](3.Java%20POO/22.ArrayList%20en%20Java.md) 43 | - [LinkedList en java](3.Java%20POO/23.LinkedList%20en%20java.md) 44 | - [Diferencias entre ArrayLists y LinkedLists](3.Java%20POO/24.Diferencias%20entre%20ArrayLists%20y%20LinkedLists.md) 45 | - [Stacks en java](3.Java%20POO/25.Stacks%20en%20java.md) 46 | - [Maps en java](3.Java%20POO/26.Maps%20en%20java.md) 47 | - [Excepciones en Java](3.Java%20POO/27.Excepciones%20en%20Java.md) 48 | - [Relaciones entre Clases en Java](3.Java%20POO/28.Relaciones%20entre%20Clases%20en%20Java.md) 49 | - [Conversiones entre Tipos de Datos](3.Java%20POO/29.Conversiones%20entre%20Tipos%20de%20Datos.md) 50 | - [ENUMS o enumeraciones en java](3.Java%20POO/30.ENUMS%20o%20enumeraciones%20en%20java.md) 51 | - [Generics o génericos en java](3.Java%20POO/31.Generics%20o%20génericos%20en%20java.md) 52 | - [JPA Java Persistence API](3.Java%20POO/32.JPA%20(Java%20Persistence%20Api).md) 53 | - [Annotations en JPA](3.Java%20POO/33.Annotations%20en%20JPA.md) 54 | - [JPA Controllers](3.Java%20POO/34.JPA%20Controllers.md) 55 | - [CRUD en JPA CREATE](3.Java%20POO/35.CRUD%20en%20JPA%20CREATE.md) 56 | - [CRUD en JPA Delete y Edit](3.Java%20POO/36.CRUD%20en%20JPA%20Delete%20y%20Edit.md) 57 | - [CRUD con JPA Find y FindEntities](3.Java%20POO/37.CRUD%20con%20JPA%20Find%20y%20FindEntities.md) 58 | - [CRUD con JPA Relacion OneToOne](3.Java%20POO/38.CRUD%20con%20JPA%20Relacion%20OneToOne.md) 59 | - [CRUD con JPA Relacion OneToMany](3.Java%20POO/39.CRUD%20con%20JPA%20Relacion%20OneToMany.md) 60 | 61 | - **Tema 4: Spring Boot** 62 | - [Librerías y Frameworks](4.Spring%20Boot/40.Librerías%20vs%20Frameworks.md) 63 | - [Spring Framework](4.Spring%20Boot/41.Spring%20Framework.md) 64 | - [Spring Boot](4.Spring%20Boot/42.Spring%20Boot.md) 65 | - [Spring Initializr](4.Spring%20Boot/43.Spring%20Initializr.md) 66 | - [Patrón MVC](4.Spring%20Boot/44.Patrón%20MVC.md) 67 | - [ApisRest](4.Spring%20Boot/45.ApisRest.md) 68 | - [Primer API con Spring Boot](4.Spring%20Boot/46.Primer%20API%20con%20Spring%20Boot.md) 69 | - [@GetMapping y @PathVariable](4.Spring%20Boot/47.GetMapping%20y%20PathVariable.md) 70 | - [@RequestParam](4.Spring%20Boot/48.@RequestParam%20.md) 71 | - [Que es JSON](4.Spring%20Boot/49.Que%20es%20JSON.md) 72 | - [@PostMapping + @RequestBody](4.Spring%20Boot/50.@PostMapping%20+%20@RequestBody.md) 73 | - [@ResponseBody + ResponseEntity](4.Spring%20Boot/51.@ResponseBody%20+%20ResponseEntity.md) 74 | - [Patrón DTO (Data Transfer Object)](4.Spring%20Boot/52.Patrón%20DTO%20(Data%20Transfer%20Object).md) 75 | - [Arquitectura multicapa](4.Spring%20Boot/53.Arquitectura%20multicapa.md) 76 | - [@Repository y @Service](4.Spring%20Boot/54.@Repository%20y%20@Service.md) 77 | - [Inversión de Control](4.Spring%20Boot/55.Inversión%20de%20Control%20.md) 78 | - [@Autowired](4.Spring%20Boot/56.@Autowired.md) 79 | - [@Data](4.Spring%20Boot/57.@Data.md) 80 | - [Hibernate](4.Spring%20Boot/58.Hibernate.md) 81 | - [Relaciones @OneToOne, @OneToMany y @ManyToMany](4.Spring%20Boot/59.Relaciones%20@OneToOne,%20@OneToMany%20y%20@ManyToMany.md) 82 | 83 | - **Tema 5: Spring Security** 84 | - [Autenticación vs Autorización](5.Spring%20Security/60.Autenticación%20vs%20Autorización.md) 85 | - [Stateful vs Stateless](5.Spring%20Security/61.Stateful%20vs%20Stateless.md) 86 | - [Roles y Permisos](5.Spring%20Security/62.%20Roles%20y%20Permisos.md) 87 | 88 | - **Tema 6: Teoría** 89 | - [Patrones vs Arquitecturas ](5.Teoría/Patrones%20vs%20Arquitecturas%20.md) --------------------------------------------------------------------------------