Sobes.tech
Middle

Quais são os tipos de classes aninhadas?

sobes.tech IA

Resposta da IA

As classes aninhadas (Nested Classes) em Java dividem-se em dois tipos principais:

  1. Classes aninhadas estáticas (Static Nested Classes)

    • Marcadas com o modificador static.
    • Comportam-se como membros estáticos normais da classe contêiner.
    • Podem aceder aos membros estáticos da classe externa (mesmo que privados).
    • Não têm acesso direto aos membros não estáticos da classe externa.
    • São criadas sem uma instância da classe externa: OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();.
  2. Classes internas (Inner Classes)

    As classes internas não são marcadas com static e estão relacionadas com uma instância da classe externa. Elas subdividem-se em:

    • Classes membro (Member Inner Classes)

      • Declaradas ao nível de um membro da classe contêiner, mas fora de seus métodos.
      • Têm acesso a todos os membros da classe externa, incluindo privados.
      • Requerem uma instância da classe externa para criar sua própria instância: OuterClass outerObject = new OuterClass(); OuterClass.MemberInnerClass innerObject = outerObject.new MemberInnerClass();.
    • Classes locais (Local Classes)

      • Criadas dentro de métodos, construtores ou blocos de inicialização.
      • Seu âmbito está limitado ao bloco onde são declaradas.
      • Não podem ser declaradas com modificadores de acesso (public, private, protected).
      • Podem aceder a variáveis locais finais ou efetivamente finais do bloco externo.
      • Não podem ser usadas fora do bloco onde são definidas.
    • Classes anónimas (Anonymous Classes)

      • São, na essência, classes locais sem nome.
      • São declaradas e instanciadas ao mesmo tempo.
      • São usadas para implementar uma classe abstrata ou uma interface "de improviso".
      • Tal como as classes locais, têm acesso a variáveis locais finais ou efetivamente finais do bloco externo.

Exemplo de estrutura:

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

    // Classe aninhada estática
    static class StaticNestedClass {
        void accessOuter() {
            // Pode aceder aos membros estáticos da classe externa
            int value = staticOuterField;
            // Não pode aceder aos membros não estáticos
            // int value2 = outerField; // Erro de compilação
        }
    }

    // Classe membro (classe interna)
    class MemberInnerClass {
        void accessOuter() {
            // Pode aceder a todos os membros da classe externa
            int value1 = outerField;
            int value2 = staticOuterField;
        }
    }

    void methodWithLocalAndAnonymous() {
        final int localVar = 10; // final ou efetivamente final

        // Classe local
        class LocalClass {
            void accessOuter() {
                // Pode aceder aos membros da classe externa e variáveis locais finais/efetivamente finais
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
            }
        }

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

        // Classe anónima (que implementa Runnable)
        Runnable anonymousRunnable = new Runnable() {
            @Override
            public void run() {
                // Pode aceder aos membros da classe externa e variáveis locais finais/efetivamente finais
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
                System.out.println("Executando com variável local: " + localValue);
            }
        };

        anonymousRunnable.run();
    }
}