Middle
Fale sobre classes aninhadas e em que casos elas são aplicadas.
sobes.tech IA
Resposta da IA
As classes aninhadas (Nested Classes) em Java são classes definidas dentro de outra classe. Elas dividem-se em dois tipos: estáticas (Static Nested Classes) e internas (Inner Classes).
Classes aninhadas estáticas
- Declaradas com o modificador
static. - Têm acesso apenas aos membros estáticos da classe externa (mesmo os ocultos).
- Não têm acesso aos membros não estáticos da classe externa.
- Para criar uma instância de uma classe aninhada estática, não é necessária uma instância da classe externa:
// Classe externa class Outer { static int outerStaticField; int outerInstanceField; // Classe aninhada estática static class StaticNested { void accessOuter() { // Acesso ao campo estático da classe externa System.out.println(Outer.outerStaticField); // Sem acesso a outerInstanceField // System.out.println(outerInstanceField); // Erro de compilação } } } // Uso da classe aninhada estática class Main { public static void main(String[] args) { Outer.StaticNested nestedObject = new Outer.StaticNested(); nestedObject.accessOuter(); } }
Classes internas
- Não são declaradas com o modificador
static. - Têm acesso completo a todos os membros da classe externa (estáticos e não estáticos, mesmo os ocultos).
- Uma instância da classe interna não pode existir sem uma instância da classe externa.
- Para criar uma instância da classe interna, é necessária uma instância da classe externa:
// Classe externa class Outer { static int outerStaticField; int outerInstanceField; // Classe interna class Inner { void accessOuter() { // Acesso ao campo estático da classe externa System.out.println(Outer.outerStaticField); // Acesso ao campo não estático da classe externa System.out.println(outerInstanceField); } } } // Uso da classe interna class Main { public static void main(String[] args) { Outer outerObject = new Outer(); Outer.Inner innerObject = outerObject.new Inner(); innerObject.accessOuter(); } }
As classes internas subdividem-se em:
- Classes internas regulares: Definidas diretamente dentro do corpo da classe externa.
- Classes internas locais: Definidas dentro de métodos, construtores ou blocos de inicialização. São visíveis apenas dentro desse bloco.
class Outer { void display() { class LocalInner { // Classe interna local void message() { System.out.println("Classe interna local"); } } LocalInner obj = new LocalInner(); obj.message(); } } - Classes internas anónimas: Classes sem nome, usadas para criar uma instância de uma classe ou interface e fornecer sua implementação imediatamente. São frequentemente usadas com ouvintes de eventos.
interface Greeting { void sayHello(); } class Main { public static void main(String[] args) { Greeting greeting = new Greeting() { // Classe interna anónima @Override public void sayHello() { System.out.println("Olá!"); } }; greeting.sayHello(); } }
Quando aplicar classes aninhadas:
- Agrupamento lógico: Se uma classe faz parte apenas de outra classe e faz sentido agrupá-las juntas. Isso melhora a legibilidade e a manutenção do código.
- Encapsulamento: As classes aninhadas podem acessar os membros da classe externa, o que garante uma relação mais estreita e a capacidade de esconder detalhes de implementação.
- Código mais legível: Quando uma pequena classe simples é usada apenas em um lugar, aninhá-la pode tornar o código mais organizado.
- Uso eficiente de recursos: As classes internas têm acesso aos membros da classe externa sem necessidade de passá-los explicitamente, o que pode simplificar o código. Um exemplo é a implementação de iteradores.
- Implementação de interfaces ou extensão de classes no contexto: As classes internas anónimas são frequentemente usadas para fornecer uma implementação compacta de interfaces ou classes abstratas "em tempo real".
- Ocultamento de implementação: Ocultar uma classe dentro de outra, tornando-a invisível de fora.
Comparação entre classes aninhadas estáticas e internas:
| Parâmetro | Classe aninhada estática | Classe interna |
|---|---|---|
Modificador static |
Sim | Não |
| Acesso aos membros da classe externa | Apenas estáticos (mesmo privados) | Todos os membros (estáticos e não estáticos, privados) |
| Requer uma instância da classe externa para criar | Não | Sim |
| Relação com a instância da classe externa | Não | Sim |
A escolha entre uma classe aninhada estática e uma interna depende de se a classe interna precisa de acesso aos membros não estáticos da classe externa. Se precisar, use a classe interna. Caso contrário, a classe aninhada estática é uma escolha mais adequada, pois não está vinculada a uma instância da classe externa e pode ser mais eficiente.