Intermediate Java concepts
Packages, exceptions, collections, enums and wrapper classes, with interactive examples.
Introduction to Intermediate Concepts
The intermediate concepts in Java are essential tools that let you write more organized, robust and efficient code. Mastering these concepts is crucial for developing professional applications.
Packages
They organize classes into logical namespaces, avoiding name conflicts and making maintenance easier.
Exceptions
They handle errors elegantly, allowing programs to recover from unexpected situations.
Collections
Flexible data structures to efficiently store and manipulate groups of objects.
Enumerations
They define fixed sets of named constants, improving code readability and safety.
Wrapper Classes
They wrap primitive types in objects, allowing their use in contexts that require objects.
Packages (Packages)
Package Structure Explorer
// 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));
}
}
📌 Package Naming Conventions:
- Use reverse domain:
com.empresa.proyecto.modulo - All letters lowercase
- Avoid Java reserved words
- Names should be descriptive and hierarchical
- Example:
org.apache.commons.math3.analysis
Exception Handling
Exception Flow Simulator
Exceptions are events that interrupt the normal execution flow. Java provides a robust mechanism for handling them.
Code that might throw exceptions
try {
// Código que puede fallar int resultado = dividir(10, 0);
System.out.println("Result: " + resultado);
}
Catches and handles specific exceptions
} catch (ArithmeticException e) {
// Maneja división por cero System.out.println("Error: " + e.getMessage());
System.out.println("No se puede dividir por cero");
}
Always runs, whether there's an exception or not
} 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;
}
Collections Framework
Java Collections Explorer
The Collections Framework provides a unified architecture for representing and manipulating collections.
List - Lists
Ordered collections that allow duplicates
// 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);
// Features:// • Mantienen orden de inserción// • Permiten acceso por índice// • Permiten elementos duplicados// • Tiempo de acceso: ArrayList O(1), LinkedList O(n)
Set - Sets
Collections that don't allow duplicates
// 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);
// Result: [1, 3, 5] (ordenado)
// Features:// • No permiten duplicados// • HashSet no mantiene orden// • TreeSet mantiene orden natural// • Operaciones O(1) promedio (HashSet)
Map - Maps
Store key-value pairs
// 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
// Features:// • Claves únicas, valores pueden repetirse// • Acceso rápido por clave O(1)// • HashMap no mantiene orden// • TreeMap mantiene orden por clave
| Interface | Implementation | Order | Duplicates | Access | Typical Use |
|---|---|---|---|---|---|
List |
ArrayList |
By index | Yes | O(1) by index | Dynamic lists |
List |
LinkedList |
Por índice | Sí | O(n) by index | Frequent insertions/deletions |
Set |
HashSet |
No | No | O(1) average | Unordered sets |
Set |
TreeSet |
Natural order | No | O(log n) | Ordered sets |
Map |
HashMap |
No | Unique keys | O(1) average | Hash tables |
Map |
TreeMap |
By key | Unique keys | O(log n) | Ordered maps |
Enumerations (Enum)
Enumeration Simulator
Enums define a fixed set of named constants, improving code readability and safety.
Days of the Week
Order States
// 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);
}
}
Wrapper Classes
Conversions between Primitive Types and Objects
Wrapper classes wrap primitive types in objects, allowing their use in collections and other contexts that require objects.
| Primitive Type | Wrapper Class | Size | Default Value | Example |
|---|---|---|---|---|
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
Useful Methods
Constants
// 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);
Memory Game: Concepts
Find the Concept Pairs
Flip the cards to find the definitions that match each concept.
Practical Exercises
Library Management System
Create a complete library system using all the concepts learned:
- Packages: Organize the code into packages:
com.biblioteca.modelo,com.biblioteca.servicio,com.biblioteca.util - Exceptions: Create custom exceptions:
LibroNoDisponibleException,UsuarioBloqueadoException - Collections: Use
HashMapto look up books by ISBN andTreeSetfor sorted users - Enums: Define
EstadoLibro(DISPONIBLE, PRESTADO, RESERVADO, REPARACION) - Wrappers: Use wrapper classes for statistical calculations
Order System with Validation
Implement an order system with robust validation:
- Exceptions: Create an exception hierarchy for different error types
- Collections: Use
ArrayListfor order items,HashSetfor unique codes - Enums: Define
EstadoPedido,CategoriaProducto,Prioridad - Wrappers: Implement calculations with
BigDecimalfor monetary precision - Validation: Use validation methods from wrapper classes
Text Analyzer with Collections
Create a text analyzer that uses collections in advanced ways:
- HashMap: Count word frequency (word → count)
- TreeMap: Sort words by descending frequency
- HashSet: Identify unique words
- ArrayList: Store words in order of appearance
- Enums: Define analysis types (FRECUENCIA, UNICAS, LONGITUD)
- Wrappers: Use
Characterfor character analysis
Game System with All Concepts
Implement a game system that integrates all the intermediate concepts:
- Packages: Organized structure:
com.juego.entidades,com.juego.mecanicas,com.juego.util - Exceptions: Exceptions for the game:
JugadorSinVidaException,ItemNoDisponibleException - Collections: Use different collections: inventory (
ArrayList), achievements (HashSet), ranking (TreeMap) - Enums: Define
Dificultad,TipoItem,EstadoJuego - Wrappers: Scoring system with precise calculations
Integrative Challenge
Question Bank: How Much Do You Know?
Question 1: What is the main advantage of using packages in Java?
Summary and Best Practices
Key Concepts
- Packages: Organize code into hierarchical namespaces
- Exceptions: Handle errors in a controlled way (checked/unchecked)
- Collections: Unified framework for data structures
- List: Ordered collections that allow duplicates
- Set: Collections that don't allow duplicates
- Map: Store key-value pairs
- Enums: Fixed sets of named constants
- Wrappers: Wrap primitive types in objects
- Autoboxing/Unboxing: Automatic conversions primitive↔wrapper
Best Practices
- Use package names based on reverse domain
- Catch specific exceptions instead of general Exception
- Use try-with-resources for auto-closeable resources
- Choose the right collection based on your needs
- Use enums instead of magic numeric constants
- Prefer valueOf() over constructors for wrappers
- Use equals() to compare wrappers, not ==
- Document exceptions thrown by methods
- Use specific imports instead of import *
Common Errors
- Not handling checked exceptions (compile error)
- Catching Exception instead of specific exceptions
- Using == to compare wrapper objects outside the cache
- Forgetting to close resources in finally blocks
- Using ArrayList when frequent insertions/deletions are needed
- Confusing HashSet with TreeSet (order vs speed)
- Not overriding equals() and hashCode() in classes used in HashSet/HashMap
- Using magic numbers instead of enums
- Not validating data when converting Strings to wrappers
Quick Reference Sheet
Packages:
package com.empresa.proyecto;
import java.util.List;
import static java.lang.Math.PI;
Exceptions:
try {
// código
} catch (IOException e) {
// manejo} finally {
// limpieza}
Collections:
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");
Final Concepts Test
Evaluate your knowledge
Answer the following questions about intermediate Java concepts
Question 1 expression in 10