Conceptos intermedios de Java
Paquetes, excepciones, colecciones, enumeraciones y clases envoltorio, con ejemplos interactivos.
Introducción a Conceptos Intermedios
Los conceptos intermedios de Java son herramientas esenciales que permiten escribir código más organizado, robusto y eficiente. Dominar estos conceptos es crucial para desarrollar aplicaciones profesionales.
Paquetes
Organizan clases en namespaces lógicos, evitando conflictos de nombres y facilitando el mantenimiento.
Excepciones
Manejan errores de manera elegante, permitiendo que los programas se recuperen de situaciones inesperadas.
Colecciones
Estructuras de datos flexibles para almacenar y manipular grupos de objetos de manera eficiente.
Enumeraciones
Definen conjuntos fijos de constantes con nombres, mejorando la legibilidad y seguridad del código.
Clases Wrapper
Envuelven tipos primitivos en objetos, permitiendo su uso en contextos que requieren objetos.
Paquetes (Packages)
Explorador de Estructura de Paquetes
// ESTRUCTURA DE DIRECTORIOS (Sistema de archivos)src/
├── com/
│ └── miapp/
│ ├── model/
│ │ ├── Usuario.java
│ │ └── Producto.java
│ ├── service/
│ │ ├── UsuarioService.java
│ │ └── ProductoService.java
│ ├── util/
│ │ ├── Validador.java
│ │ └── Calculadora.java
│ └── main/
│ └── MainApp.java
// DECLARACIÓN DE PAQUETE (en cada archivo .java)package com.miapp.model; // En Usuario.java
// IMPORTACIÓN DE CLASESimport java.util.ArrayList; // Import específicoimport java.util.*; // Import de todo el paqueteimport com.miapp.model.Usuario; // Import de nuestro propio paquete
// IMPORT ESTÁTICO (para métodos/constantes estáticas)import static java.lang.Math.PI;
import static java.lang.Math.pow;
// CLASE PRINCIPAL QUE USA LOS PAQUETESpackage com.miapp.main;
import com.miapp.model.Usuario;
import com.miapp.model.Producto;
import com.miapp.service.UsuarioService;
import static java.lang.System.out;
public class MainApp {
public static void main(String[] args) {
// Usar clases importadas Usuario usuario = new Usuario("Juan", "juan@email.com");
UsuarioService service = new UsuarioService();
// Usar import estático out.println("PI = " + PI);
out.println("2^3 = " + pow(2, 3));
}
}
📌 Convenciones de Nombres para Paquetes:
- Usar dominio inverso:
com.empresa.proyecto.modulo - Todas las letras en minúscula
- Evitar palabras reservadas de Java
- Los nombres deben ser descriptivos y jerárquicos
- Ejemplo:
org.apache.commons.math3.analysis
Manejo de Excepciones
Simulador de Flujo de Excepciones
Las excepciones son eventos que interrumpen el flujo normal de ejecución. Java proporciona un mecanismo robusto para manejarlas.
Código que puede lanzar excepciones
try {
// Código que puede fallar int resultado = dividir(10, 0);
System.out.println("Resultado: " + resultado);
}
Captura y maneja excepciones específicas
} catch (ArithmeticException e) {
// Maneja división por cero System.out.println("Error: " + e.getMessage());
System.out.println("No se puede dividir por cero");
}
Se ejecuta siempre, haya o no excepción
} finally {
// Código de limpieza System.out.println("Operación finalizada");
cerrarRecursos();
}
// JERARQUÍA DE EXCEPCIONESThrowable (clase base)
├── Error (errores graves, no se deben capturar)
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ └── ...
└── Exception (excepciones recuperables)
├── RuntimeException (unchecked - no requiere declaración)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ArithmeticException
│ ├── IllegalArgumentException
│ └── ...
└── IOException (checked - requiere manejo)
├── FileNotFoundException
├── EOFException
└── ...
// EJEMPLOS COMPLETOS
// 1. EXCEPCIÓN CHECKED (obligatorio manejar)public void leerArchivo(String ruta) {
try {
FileReader reader = new FileReader(ruta);
// Leer archivo... } catch (FileNotFoundException e) {
System.err.println("Archivo no encontrado: " + e.getMessage());
} catch (IOException e) {
System.err.println("Error de E/S: " + e.getMessage());
}
}
// 2. EXCEPCIÓN UNCHECKED (opcional manejar)public int dividir(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Divisor no puede ser cero");
}
return a / b;
}
// 3. MULTI-CATCH (Java 7+)
try {
// Código que puede lanzar múltiples excepciones} catch (NullPointerException | IllegalArgumentException e) {
System.err.println("Error de argumento: " + e.getMessage());
}
// 4. TRY-WITH-RESOURCES (Java 7+)
try (FileReader reader = new FileReader("archivo.txt");
BufferedReader br = new BufferedReader(reader)) {
String linea;
while ((linea = br.readLine()) != null) {
System.out.println(linea);
}
} catch (IOException e) {
System.err.println("Error al leer archivo: " + e.getMessage());
}
// 5. EXCEPCIONES PERSONALIZADASclass SaldoInsuficienteException extends Exception {
private double saldo;
private double montoRequerido;
public SaldoInsuficienteException(double saldo, double montoRequerido) {
super("Saldo insuficiente: $" + saldo + ", se requiere: $" + montoRequerido);
this.saldo = saldo;
this.montoRequerido = montoRequerido;
}
public double getSaldo() { return saldo; }
public double getMontoRequerido() { return montoRequerido; }
}
// USO DE EXCEPCIÓN PERSONALIZADApublic void retirar(double cantidad) throws SaldoInsuficienteException {
if (cantidad > saldo) {
throw new SaldoInsuficienteException(saldo, cantidad);
}
saldo -= cantidad;
}
Colecciones Framework
Java Explorador de Colecciones
El Framework de Colecciones proporciona una arquitectura unificada para representar y manipular colecciones.
List - Listas
Colecciones ordenadas que permiten duplicados
// ArrayList - Array redimensionableList frutas = new ArrayList<>();
frutas.add("Manzana");
frutas.add("Banana");
frutas.add("Naranja");
// LinkedList - Lista doblemente enlazadaList numeros = new LinkedList<>();
numeros.add(1);
numeros.add(2);
numeros.add(3);
// Características:// • Mantienen orden de inserción// • Permiten acceso por índice// • Permiten elementos duplicados// • Tiempo de acceso: ArrayList O(1), LinkedList O(n)
Set - Conjuntos
Colecciones que no permiten duplicados
// HashSet - Basado en tabla hashSet colores = new HashSet<>();
colores.add("Rojo");
colores.add("Verde");
colores.add("Azul");
colores.add("Rojo"); // No se agrega (duplicado)
// TreeSet - Ordenado automáticamenteSet numeros = new TreeSet<>();
numeros.add(5);
numeros.add(1);
numeros.add(3);
// Resultado: [1, 3, 5] (ordenado)
// Características:// • No permiten duplicados// • HashSet no mantiene orden// • TreeSet mantiene orden natural// • Operaciones O(1) promedio (HashSet)
Map - Mapas
Almacenan pares clave-valor
// HashMap - Basado en tabla hashMap capitales = new HashMap<>();
capitales.put("España", "Madrid");
capitales.put("Francia", "París");
capitales.put("Italia", "Roma");
// TreeMap - Ordenado por claveMap edades = new TreeMap<>();
edades.put("Ana", 25);
edades.put("Carlos", 30);
edades.put("Beatriz", 28);
// Ordenado: Ana, Beatriz, Carlos
// Características:// • Claves únicas, valores pueden repetirse// • Acceso rápido por clave O(1)// • HashMap no mantiene orden// • TreeMap mantiene orden por clave
| Interfaz | Implementación | Orden | Duplicados | Acceso | Uso Típico |
|---|---|---|---|---|---|
List |
ArrayList |
Por índice | Sí | O(1) por índice | Listas dinámicas |
List |
LinkedList |
Por índice | Sí | O(n) por índice | Inserciones/eliminaciones frecuentes |
Set |
HashSet |
No | No | O(1) promedio | Conjuntos sin orden |
Set |
TreeSet |
Orden natural | No | O(log n) | Conjuntos ordenados |
Map |
HashMap |
No | Claves únicas | O(1) promedio | Tablas hash |
Map |
TreeMap |
Por clave | Claves únicas | O(log n) | Mapas ordenados |
Enumeraciones (Enum)
Simulador de Enumeraciones
Los enums definen un conjunto fijo de constantes con nombres, mejorando la legibilidad y seguridad del código.
Días de la Semana
Estados de Pedido
// ENUM BÁSICOpublic enum DiaSemana {
LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO
}
// ENUM CON ATRIBUTOS Y MÉTODOSpublic enum EstadoPedido {
PENDIENTE("En espera de procesamiento", 1),
PROCESANDO("En preparación", 2),
ENVIADO("En camino al cliente", 3),
ENTREGADO("Entregado satisfactoriamente", 4),
CANCELADO("Pedido cancelado", 0);
private final String descripcion;
private final int prioridad;
EstadoPedido(String descripcion, int prioridad) {
this.descripcion = descripcion;
this.prioridad = prioridad;
}
public String getDescripcion() { return descripcion; }
public int getPrioridad() { return prioridad; }
public boolean esFinal() {
return this == ENTREGADO || this == CANCELADO;
}
}
// ENUM CON MÉTODOS ABSTRACTOSpublic enum OperacionMatematica {
SUMA("+") {
public double aplicar(double x, double y) { return x + y; }
},
RESTA("-") {
public double aplicar(double x, double y) { return x - y; }
},
MULTIPLICACION("*") {
public double aplicar(double x, double y) { return x * y; }
},
DIVISION("/") {
public double aplicar(double x, double y) {
if (y == 0) throw new ArithmeticException("División por cero");
return x / y;
}
};
private final String simbolo;
OperacionMatematica(String simbolo) {
this.simbolo = simbolo;
}
public String getSimbolo() { return simbolo; }
// Método abstracto que cada constante debe implementar public abstract double aplicar(double x, double y);
}
// USO DE ENUMSpublic class EjemploEnums {
public static void main(String[] args) {
// Valores básicos DiaSemana hoy = DiaSemana.LUNES;
System.out.println("Hoy es: " + hoy);
// Iterar sobre todos los valores for (DiaSemana dia : DiaSemana.values()) {
System.out.println(dia);
}
// Enums avanzados EstadoPedido estado = EstadoPedido.PROCESANDO;
System.out.println("Estado: " + estado);
System.out.println("Descripción: " + estado.getDescripcion());
System.out.println("Es estado final: " + estado.esFinal());
// Switch con enum switch (estado) {
case PENDIENTE:
System.out.println("El pedido está pendiente");
break;
case PROCESANDO:
System.out.println("El pedido se está procesando");
break;
case ENTREGADO:
System.out.println("¡Pedido entregado!");
break;
}
// Enum con métodos OperacionMatematica op = OperacionMatematica.SUMA;
double resultado = op.aplicar(10, 5);
System.out.println("10 " + op.getSimbolo() + " 5 = " + resultado);
// Comparación de enums if (estado == EstadoPedido.PROCESANDO) {
System.out.println("El pedido está en proceso");
}
// Convertir String a enum String texto = "ENTREGADO";
EstadoPedido estadoDesdeTexto = EstadoPedido.valueOf(texto);
System.out.println("Estado desde texto: " + estadoDesdeTexto);
}
}
Clases Wrapper
Conversiones entre Tipos Primitivos y Objetos
Las clases wrapper envuelven tipos primitivos en objetos, permitiendo su uso en colecciones y otros contextos que requieren objetos.
| Tipo Primitivo | Clase Wrapper | Tamaño | Valor por Defecto | Ejemplo |
|---|---|---|---|---|
byte |
Byte |
8 bits | 0 | Byte.valueOf((byte)10) |
short |
Short |
16 bits | 0 | Short.valueOf((short)100) |
int |
Integer |
32 bits | 0 | Integer.valueOf(1000) |
long |
Long |
64 bits | 0L | Long.valueOf(100000L) |
float |
Float |
32 bits | 0.0f | Float.valueOf(3.14f) |
double |
Double |
64 bits | 0.0d | Double.valueOf(3.14159) |
char |
Character |
16 bits | '\u0000' | Character.valueOf('A') |
boolean |
Boolean |
1 bit | false | Boolean.valueOf(true) |
Autoboxing/Unboxing
Métodos Utiles
Constantes
// AUTOBOXING Y UNBOXING (Java 5+)
// Autoboxing: conversión automática primitivo → wrapperInteger numeroObj = 42; // Equivale a: Integer.valueOf(42)
Double precioObj = 19.99; // Equivale a: Double.valueOf(19.99)
Boolean esVerdadero = true; // Equivale a: Boolean.valueOf(true)
// Unboxing: conversión automática wrapper → primitivoint numero = numeroObj; // Equivale a: numeroObj.intValue()
double precio = precioObj; // Equivale a: precioObj.doubleValue()
boolean valor = esVerdadero; // Equivale a: esVerdadero.booleanValue()
// MÉTODOS ÚTILES DE CLASES WRAPPER
// 1. Conversión de String a tipos numéricosString textoNumero = "123";
int valorInt = Integer.parseInt(textoNumero); // 123
double valorDouble = Double.parseDouble("3.14"); // 3.14
boolean valorBool = Boolean.parseBoolean("true"); // true
// 2. Conversión a StringString str1 = Integer.toString(456); // "456"
String str2 = Double.toString(2.718); // "2.718"
String str3 = Boolean.toString(false); // "false"
// 3. Comparación de objetosInteger a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b); // true (cache de -128 a 127)
System.out.println(c == d); // false (fuera del cache)
System.out.println(c.equals(d)); // true (comparación por valor)
// 4. Constantes útilesSystem.out.println("Máximo int: " + Integer.MAX_VALUE); // 2147483647
System.out.println("Mínimo int: " + Integer.MIN_VALUE); // -2147483648
System.out.println("Bytes en int: " + Integer.BYTES); // 4
System.out.println("Bits en int: " + Integer.SIZE); // 32
// 5. Métodos de Characterchar letra = 'A';
System.out.println(Character.isLetter(letra)); // true
System.out.println(Character.isDigit(letra)); // false
System.out.println(Character.isUpperCase(letra)); // true
System.out.println(Character.toLowerCase(letra)); // 'a'
// USO EN COLECCIONES (necesitan objetos)List numeros = new ArrayList<>();
numeros.add(1); // Autoboxing: int → Integer
numeros.add(2);
numeros.add(3);
int suma = 0;
for (Integer num : numeros) {
suma += num; // Unboxing: Integer → int
}
System.out.println("Suma: " + suma);
// COMPARACIÓN SEGURA (evitar NullPointerException)Integer posibleNull = obtenerNumero();
int valorSeguro = (posibleNull != null) ? posibleNull : 0;
// MÉTODOS DE CONVERSIÓN ADICIONALESint hex = Integer.parseInt("FF", 16); // 255 en hexadecimalint bin = Integer.parseInt("1010", 2); // 10 en binarioString binStr = Integer.toBinaryString(10); // "1010"
String hexStr = Integer.toHexString(255); // "ff"
// WRAPPER PARA TIPOS GENÉRICOSpublic class Caja {
private T valor;
public Caja(T valor) {
this.valor = valor;
}
public double obtenerValorDouble() {
return valor.doubleValue(); // Método de Number }
}
Caja cajaEntero = new Caja<>(100);
Caja cajaDouble = new Caja<>(3.14);
Juego de Memoria: Conceptos
Encuentra las Parejas de Conceptos
Voltea las cartas para encontrar las definiciones que corresponden a cada concepto.
Ejercicios Prácticos
Sistema de Gestión de Biblioteca
Crea un sistema completo para una biblioteca usando todos los conceptos aprendidos:
- Paquetes: Organiza el código en paquetes:
com.biblioteca.modelo,com.biblioteca.servicio,com.biblioteca.util - Excepciones: Crea excepciones personalizadas:
LibroNoDisponibleException,UsuarioBloqueadoException - Colecciones: Usa
HashMappara buscar libros por ISBN yTreeSetpara usuarios ordenados - Enums: Define
EstadoLibro(DISPONIBLE, PRESTADO, RESERVADO, REPARACION) - Wrappers: Usa clases wrapper para cálculos estadísticos
Sistema de Pedidos con Validación
Implementa un sistema de pedidos con validación robusta:
- Excepciones: Crea jerarquía de excepciones para diferentes tipos de errores
- Colecciones: Usa
ArrayListpara items del pedido,HashSetpara códigos únicos - Enums: Define
EstadoPedido,CategoriaProducto,Prioridad - Wrappers: Implementa cálculos con
BigDecimalpara precisión monetaria - Validación: Usa métodos de validación de clases wrapper
Analizador de Texto con Colecciones
Crea un analizador de texto que use colecciones de manera avanzada:
- HashMap: Contar frecuencia de palabras (palabra → cantidad)
- TreeMap: Ordenar palabras por frecuencia descendente
- HashSet: Identificar palabras únicas
- ArrayList: Almacenar palabras en orden de aparición
- Enums: Definir tipos de análisis (FRECUENCIA, UNICAS, LONGITUD)
- Wrappers: Usar
Characterpara análisis de caracteres
Sistema de Juego con Todos los Conceptos
Implementa un sistema de juego que integre todos los conceptos intermedios:
- Paquetes: Estructura organizada:
com.juego.entidades,com.juego.mecanicas,com.juego.util - Excepciones: Excepciones para el juego:
JugadorSinVidaException,ItemNoDisponibleException - Colecciones: Usar diferentes colecciones: inventario (
ArrayList), logros (HashSet), ranking (TreeMap) - Enums: Definir
Dificultad,TipoItem,EstadoJuego - Wrappers: Sistema de puntuación con cálculos precisos
Desafío Integrador
Banco de Preguntas: ¿Cuánto Sabes?
Pregunta 1: ¿Cuál es la ventaja principal de usar paquetes en Java?
Resumen y Buenas Prácticas
Conceptos Clave
- Paquetes: Organizan código en namespaces jerárquicos
- Excepciones: Manejan errores de forma controlada (checked/unchecked)
- Colecciones: Framework unificado para estructuras de datos
- List: Colecciones ordenadas que permiten duplicados
- Set: Colecciones que no permiten duplicados
- Map: Almacenan pares clave-valor
- Enums: Conjuntos fijos de constantes con nombres
- Wrappers: Envuelven tipos primitivos en objetos
- Autoboxing/Unboxing: Conversiones automáticas primitivo↔wrapper
Buenas Prácticas
- Usar nombres de paquete basados en dominio inverso
- Capturar excepciones específicas en lugar de Exception general
- Usar try-with-resources para recursos auto-cerrables
- Elegir la colección adecuada según las necesidades
- Usar enums en lugar de constantes numéricas mágicas
- Preferir valueOf() sobre constructores para wrappers
- Usar equals() para comparar wrappers, no ==
- Documentar excepciones lanzadas por métodos
- Usar imports específicos en lugar de import *
Errores Comunes
- No manejar excepciones checked (error de compilación)
- Capturar Exception en lugar de excepciones específicas
- Usar == para comparar objetos wrapper fuera del cache
- Olvidar cerrar recursos en bloques finally
- Usar ArrayList cuando se necesitan inserciones/eliminaciones frecuentes
- Confundir HashSet con TreeSet (orden vs velocidad)
- No sobrescribir equals() y hashCode() en clases usadas en HashSet/HashMap
- Usar números mágicos en lugar de enums
- No validar datos al convertir Strings a wrappers
Hoja de Referencia Rápida
Paquetes:
package com.empresa.proyecto;
import java.util.List;
import static java.lang.Math.PI;
Excepciones:
try {
// código
} catch (IOException e) {
// manejo} finally {
// limpieza}
Colecciones:
List lista = new ArrayList<>();
Set conjunto = new HashSet<>();
Map mapa = new HashMap<>();
Enums:
enum Color { ROJO, VERDE, AZUL }
Color c = Color.ROJO;
Wrappers:
Integer i = 42; // autoboxing
int j = i; // unboxing
int k = Integer.parseInt("123");
Test Final de Conceptos
Evalúa tu conocimiento
Responde las siguientes preguntas sobre conceptos intermedios de Java
Pregunta 1 de 10