Trabalhando com Classes Internas em Java

Uma classe interna não estática é definida dentro de outra classe sem o modificador static. Diferentemente de classes regulares, ela mantém uma referência implícita à instância da classe externa que a criou.

Características principais:

  • Objetos de classes internas não estáticas existem apenas como parte de objetos da classe externa
  • Têm acesso direto a todos os membros da classe externa, incluindo privados
  • A classe externa não pode acessar membros da classe interna diretamente
  • Não podem conter membros estáticos como métodos, atributos ou blocos de inicialização estáticos

Acesso a membros:

Dentro de uma classe interna, usamos this para referenciar membros da própria classe. Para acessar membros da classe externa, utilizamos NomeClasseExterno.this.

Exemplo prático:
class Empresa {
    private String nome = "TechCorp";
    
    public void exibirInfo() {
        System.out.println(nome);
    }
    
    public class Funcionario {
        private String nome = "João";
        
        public void apresentar() {
            System.out.println(nome); // João
            System.out.println(Empresa.this.nome); // TechCorp
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Empresa.Funcionario func = new Empresa().new Funcionario();
        func.apresentar();
    }
}

Classes Inetrnas Estáticas

Uma classe interna estática é definida com o modificador static dentro de outra classe. Ela se comporta como um membro estático da classe externa.

Características principais:

  • Pode ser instanciada sem necessidade de uma instância da classe externa
  • Só tem acesso a membros estáticos da classe externa
  • É carregada na memória de forma independente da classe externa
  • É útil para agrupar classes que têm uma relação conceitual forte
Exemplo prático:
class Database {
    private int porta = 3306;
    private static String driver = "MySQL";
    
    public static class Configuracao {
        public void exibirDriver() {
            System.out.println(driver); // Funciona
            // System.out.println(porta); // Erro de compilação
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Database.Configuracao config = new Database.Configuracao();
        config.exibirDriver();
    }
}

Classes Anônimas

Classes anônimas são úteis quando precisamos de uma implementação única e descartável, sem necessidade de nomear a classe formalmente. São muito utilizadas em listeners de eventos, calbacks e implementações rápidas de interfaces.

Características principais:

  • Não têm nome definido
  • Podem implementar uma interface ou estender uma classe
  • Têm acesso limitado ao escopo externo em alguns contextos
  • São идеais para operações pontuais
Exemplo prático:
interface Processador {
    void executar();
}

public class Main {
    public void processar(Processador p) {
        p.executar();
    }
    
    public static void main(String[] args) {
        Main app = new Main();
        
        app.processar(new Processador() {
            @Override
            public void executar() {
                System.out.println("Primeira implementação");
            }
        });
        
        app.processar(new Processador() {
            @Override
            public void executar() {
                System.out.println("Segunda implementação");
            }
        });
    }
}

Classes Locais

Classes locais são definidas dentro de um método, tendo seu escopo restrito exclusivamente a esse método. São raramente utilizadas em projetos reais devido às suas limitações de visibilidade.

Características principais:

  • Visibilidade restrita ao método onde são definidas
  • Não podem ter modificadores de acesso
  • Podem acessar membros finais ou efetivamente finais do método
  • Úteis quando a lógica é extremamente específica daquele método
Exemplo prático:
public class Gerenciador {
    public void iniciar() {
        class Timer {
            public void iniciarContagem() {
                System.out.println("Iniciando contagem...");
            }
        }
        
        Timer cronometro = new Timer();
        cronometro.iniciarContagem();
    }
    
    public static void main(String[] args) {
        new Gerenciador().iniciar();
    }
}

Tags: java inner-classes anonymous-class static-class local-class

Publicado em 10-10 10:13