Fundamentos de Java
La POO organiza el software en torno a clases y objetos. Sus pilares son:
- Encapsulación: oculta detalles internos.
- Herencia: permite reutilizar código.
- Polimorfismo: permite comportamientos variables.
// Clase base con encapsulación
public class Animal {
private String nombre;
public Animal(String nombre) {
this.nombre = nombre;
}
public String getNombre() { return nombre; }
public void hablar() {
System.out.println("Sonido genérico");
}
}
// Clase hija con herencia y polimorfismo
public class Perro extends Animal {
public Perro(String nombre) {
super(nombre);
}
@Override
public void hablar() {
System.out.println(getNombre() + " dice: Guau!");
}
}
Las colecciones almacenan múltiples elementos:
- List: ordenada, permite duplicados.
- Set: no permite duplicados.
- Map: pares clave-valor únicos.
List<String> lista = new ArrayList<>();
lista.add("A"); lista.add("A"); // permite duplicados
Set<String> conjunto = new HashSet<>();
conjunto.add("A"); conjunto.add("A"); // ignora duplicado
Map<String, Integer> mapa = new HashMap<>();
mapa.put("A", 1); mapa.put("B", 2); // clave única
Los Generics permiten definir clases y métodos que operan sobre cualquier tipo sin perder seguridad de tipo.
// Clase genérica con tipo T
public class Caja<T> {
private T contenido;
public void guardar(T item) { contenido = item; }
public T obtener() { return contenido; }
}
Java usa try-catch-finally para manejar errores:
- Checked: deben capturarse (IOException).
- Unchecked: no obligatorias (NullPointerException).
try {
int resultado = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Error: división por cero");
} finally {
System.out.println("Bloque finally ejecutado");
}
Java 8 introdujo programación funcional:
- Lambdas: funciones anónimas.
- Streams: procesamiento funcional.
- Optional: evita errores por
null.
List<String> nombres = Arrays.asList("Emilio", "Juan", "Esteban");
List<String> filtrados = nombres.stream()
.filter(n -> n.startsWith("E"))
.collect(Collectors.toList());
Optional<String> nombre = Optional.of("Emilio");
nombre.ifPresent(System.out::println);
Permite ejecutar tareas en paralelo:
- Thread: clase base.
- Runnable: interfaz funcional.
- ExecutorService: pool de hilos.
- synchronized: sincronización de acceso.
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("Tarea concurrente"));
executor.shutdown();
Java gestiona memoria automáticamente:
- Stack: variables locales.
- Heap: objetos dinámicos.
- Referencias: fuertes, débiles, suaves.
WeakReference<Object> referenciaDebil = new WeakReference<>(new Object());
Java incluye herramientas como:
enum,record,vartry-with-resources,CompletableFuture,Reflection
enum Rol { ADMIN, USUARIO, INVITADO }
public record Persona(String nombre, int edad) {}
var mensaje = "Hola Moleculax";
try (BufferedReader br = new BufferedReader(new FileReader("archivo.txt"))) {
System.out.println(br.readLine());
}
CompletableFuture.supplyAsync(() -> "Resultado")
.thenAccept(System.out::println);
Class<?> clase = Class.forName("java.util.ArrayList");
System.out.println(clase.getMethods().length);