Sobes.tech
Middle

¿Qué tipos de clases anidadas existen?

sobes.tech AI

Respuesta de la IA

Las clases anidadas (Nested Classes) en Java se dividen en dos tipos principales:

  1. Clases anidadas estáticas (Static Nested Classes)

    • Marcadas con el modificador static.
    • Se comportan como miembros estáticos normales de la clase contenedora.
    • Pueden acceder a los miembros estáticos de la clase externa (incluso si son privados).
    • No tienen acceso directo a los miembros no estáticos de la clase externa.
    • Se crean sin una instancia de la clase externa: OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();.
  2. Clases internas (Inner Classes)

    Las clases internas no están marcadas con static y están relacionadas con una instancia de la clase externa. Se subdividen en:

    • Clases miembro (Member Inner Classes)

      • Se declaran a nivel de miembro de la clase contenedora, pero fuera de sus métodos.
      • Tienen acceso a todos los miembros de la clase externa, incluyendo los privados.
      • Requieren una instancia de la clase externa para crear su propia instancia: OuterClass outerObject = new OuterClass(); OuterClass.MemberInnerClass innerObject = outerObject.new MemberInnerClass();.
    • Clases locales (Local Classes)

      • Se crean dentro de métodos, constructores o bloques de inicialización.
      • Su ámbito está limitado al bloque en el que se declaran.
      • No se pueden declarar con modificadores de acceso (public, private, protected).
      • Pueden acceder a variables locales finales o efectivamente finales del bloque externo.
      • No pueden usarse fuera del bloque donde se definen.
    • Clases anónimas (Anonymous Classes)

      • Son, en esencia, clases locales sin nombre.
      • Se declaran e instancian al mismo tiempo.
      • Se usan para implementar clases abstractas o interfaces "sobre la marcha".
      • Al igual que las clases locales, tienen acceso a variables locales finales o efectivamente finales del bloque externo.

Ejemplo de estructura:

class OuterClass {
    private int outerField;
    private static int staticOuterField;

    // Clase anidada estática
    static class StaticNestedClass {
        void accessOuter() {
            // Puede acceder a miembros estáticos de la clase externa
            int value = staticOuterField;
            // No puede acceder a miembros no estáticos
            // int value2 = outerField; // Error de compilación
        }
    }

    // Clase miembro (clase interna)
    class MemberInnerClass {
        void accessOuter() {
            // Puede acceder a todos los miembros de la clase externa
            int value1 = outerField;
            int value2 = staticOuterField;
        }
    }

    void methodWithLocalAndAnonymous() {
        final int localVar = 10; // final o efectivamente final

        // Clase local
        class LocalClass {
            void accessOuter() {
                // Puede acceder a miembros de la clase externa y variables locales finales/efectivamente finales
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
            }
        }

        LocalClass localObj = new LocalClass();
        localObj.accessOuter();

        // Clase anónima (que implementa Runnable)
        Runnable anonymousRunnable = new Runnable() {
            @Override
            public void run() {
                // Puede acceder a miembros de la clase externa y variables locales finales/efectivamente finales
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
                System.out.println("Ejecutando con variable local: " + localValue);
            }
        };

        anonymousRunnable.run();
    }
}