Java Academy · Lección

Elección de la estrategia de anidamiento adecuada

Decida entre las variantes de clases anidadas según el acoplamiento, las necesidades de acceso y la legibilidad.

Lección 4 de 414 pasos

Elección de la estrategia de anidamiento adecuada es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

Elegir la estrategia de anidamiento adecuada

Java ofrece cuatro opciones de anidamiento: de nivel superior, anidada estática, interna (no estática) y local/anónima. La elección adecuada depende del acoplamiento, las necesidades de acceso y el ámbito de reutilización.

Árbol de decisión

Hágase estas preguntas para elegir:

  1. ¿La clase se utiliza únicamente dentro de la clase externa? → Considere anidarla
  2. ¿Necesita la instancia externa? → Clase interna; de lo contrario → Clase anidada estática
  3. ¿Se utiliza únicamente en un método? → Clase local o anónima
  4. ¿Implementa un único método? → Expresión lambda

Clase de nivel superior

Utilice una clase de nivel superior cuando el tipo tenga un uso amplio en toda la base de código, represente un concepto clave del dominio o vaya a ser importado por muchas otras clases.

// Top-level: used across many packages
public class Product {
    // ...
}

public interface Repository<T, ID> {
    Optional<T> findById(ID id);
    void save(T entity);
}

// These belong in separate .java files and are widely imported

Clase anidada estática

Utilice una clase anidada estática cuando solo tenga sentido en el contexto de la clase externa, no necesite la instancia externa y deba ser accesible desde el exterior.

class Graph {
    // Edge only makes sense in the context of a Graph
    public static class Edge {
        public final int from, to, weight;
        public Edge(int from, int to, int weight) {
            this.from = from; this.to = to; this.weight = weight;
        }
    }

    private List<Edge> edges = new ArrayList<>();

    public void addEdge(int from, int to, int weight) {
        edges.add(new Edge(from, to, weight));
    }
}

Clase interna (no estática)

Utilice una clase interna cuando tenga un vínculo conceptual fuerte con la instancia externa y deba acceder a sus miembros privados, como en el caso de iteradores u objetos auxiliares estrechamente acoplados.

class DataStore<T> {
    private final List<T> data;

    DataStore(List<T> data) { this.data = data; }

    // Must access data — inner class makes sense
    class Snapshot {
        private final List<T> copy;

        Snapshot() { this.copy = List.copyOf(data); } // accesses outer

        T get(int idx) { return copy.get(idx); }
        int size()     { return copy.size(); }
    }

    Snapshot snapshot() { return new Snapshot(); }
}

Clase local

Utilice una clase local cuando solo se necesite en un único método, sea suficientemente compleja para tener varios métodos o estado y quiera mantener el ámbito lo más reducido posible.

static int countWords(String text, boolean caseSensitive) {
    class WordCounter {
        Map<String, Integer> counts = new HashMap<>();

        void count(String word) {
            String key = caseSensitive ? word : word.toLowerCase();
            counts.merge(key, 1, Integer::sum);
        }

        int uniqueCount() { return counts.size(); }
    }

    WordCounter wc = new WordCounter();
    for (String w : text.split("\\s+")) wc.count(w);
    return wc.uniqueCount();
}
System.out.println(countWords("the cat sat on the mat", false)); // 5

Clase anónima frente a lambda

Utilice una clase anónima cuando necesite varios métodos o extender una clase abstracta. Utilice una expresión lambda para las interfaces SAM.

// Lambda: clean for SAM
list.sort((a, b) -> a.compareTo(b));

// Anonymous: multi-method, or extending abstract class
java.util.TimerTask task = new java.util.TimerTask() {
    @Override public void run() { System.out.println("Tick!"); }
};
// TimerTask is abstract class — can't use lambda directly

Tabla resumen

Referencia rápida:

  • De nivel superior: reutilización amplia, tipos de API pública
  • Anidada estática: agrupación lógica, sin necesidad de una instancia externa
  • Interna: estrechamente vinculada a la instancia externa, necesita acceso privado
  • Local: ámbito limitado al método, suficientemente compleja para una clase
  • Anónima: implementación puntual y de corta duración
  • Lambda: interfaz SAM, sin estado y concisa

Práctica: diseño de un cliente HTTP

Aplicación de la estrategia de anidamiento al diseño realista de un cliente HTTP.

class HttpClient {
    // Static nested: request config has no outer reference
    public static class RequestConfig {
        public final int timeoutMs;
        public final String userAgent;
        RequestConfig(int timeout, String ua) { this.timeoutMs = timeout; this.userAgent = ua; }
    }

    // Static nested: response is standalone data carrier
    public static class Response {
        public final int statusCode;
        public final String body;
        Response(int code, String body) { this.statusCode = code; this.body = body; }
    }

    private final RequestConfig config;
    HttpClient(RequestConfig config) { this.config = config; }

    public Response get(String url) {
        // Implementation using this.config
        return new Response(200, "body");
    }
}

Evitar el anidamiento excesivo

Evite anidar más de un nivel. Las clases profundamente anidadas son difíciles de recorrer y probar. Si se vuelven complejas, extráigalas a clases de nivel superior o con acceso limitado al paquete.

Alternativa con acceso limitado al paquete

En lugar de anidar una clase, considere declararla con acceso limitado al paquete, es decir, sin modificador de acceso. Solo será visible dentro del paquete, pero resultará más fácil de probar y mantener que una clase anidada.

// In package com.example.order:

// Package-private: visible in package, no nesting
class OrderLine {  // no 'public' modifier
    final String sku;
    final int qty;
    OrderLine(String sku, int qty) { this.sku = sku; this.qty = qty; }
}

// Public class in same package can use OrderLine freely
public class Order {
    private List<OrderLine> lines = new ArrayList<>();
    // ...
}

Registros e interfaces selladas como alternativas

Las funcionalidades modernas de Java, como los registros y las interfaces selladas, a menudo eliminan la necesidad de patrones de anidamiento complejos.

// Instead of nested inner class hierarchy:
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double r) implements Shape {}
record Rectangle(double w, double h) implements Shape {}
record Triangle(double b, double h) implements Shape {}

static double area(Shape s) {
    return switch (s) {
        case Circle c      -> Math.PI * c.r() * c.r();
        case Rectangle r   -> r.w() * r.h();
        case Triangle t    -> 0.5 * t.b() * t.h();
    };
}

Comprobación rápida

¿Cuándo es mejor elegir una clase interna (no estática) en lugar de una clase anidada estática?

Repaso: elegir la estrategia de anidamiento adecuada

Ideas clave:

  • De nivel superior: tipos públicos que se utilizan ampliamente en toda la base de código
  • Anidada estática: agrupada lógicamente con la clase externa, sin necesidad de una instancia externa
  • Clase interna: estrechamente vinculada a la instancia externa, con acceso a miembros privados
  • Clase local: ámbito limitado al método, suficientemente compleja para tener varios métodos
  • Clase anónima: implementación puntual que combina la declaración y la instanciación
  • Expresión lambda: la opción más limpia para las interfaces SAM; considérela al sustituir clases anónimas
Gratis para empezar

Aprende Java con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
104
Lecciones
374

Preguntas frecuentes

¿La lección «Elección de la estrategia de anidamiento adecuada» es gratis?

Sí — el texto completo de «Elección de la estrategia de anidamiento adecuada» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Elección de la estrategia de anidamiento adecuada»?

Decida entre las variantes de clases anidadas según el acoplamiento, las necesidades de acceso y la legibilidad. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Elección de la estrategia de anidamiento adecuada»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Clases anidadas estáticas
  2. Clases internas y acceso a la clase externa
  3. Clases locales y anónimas
  4. Elección de la estrategia de anidamiento adecuada
← Volver a Java Academy