Qual é a diferença entre uma classe interna e uma classe aninhada estática em java? quando você usaria um sobre o outro?

A2A Qual é a diferença entre uma classe interna e uma classe aninhada estática em Java? Quando você usaria um sobre o outro?

Uma classe interna é qualquer classe que esteja contida em outra classe; portanto, uma classe aninhada estática é um tipo de classe interna.

Três maneiras que eu conheço (pode haver outras) de como você pode executar classes internas são:

Classe aninhada

  1. classe pública NestedExample {classe pública NestedClass {void doSomething () {System.out.println ("something"); }} public void someMethod () {NestedClass nc = new NestedClass (); nc.doAlgo (); }}

Classe aninhada em um método

  1. public class MethodExample {public void someMethod () {class NestedMethodClass {void doSomething () {System.out.println ("something"); }} NestedMethodClass nme = new NestedMethodClass (); nme.doSomething (); }}

E classe aninhada estática

  1. classe pública StaticExample {classe estática StaticClass {void doSomething () {System.out.println ("something"); }}}

Não tenho certeza se uma classe aninhada estática realmente faz muito de algo que é realmente diferente de ter seus métodos e membros como parte da classe pai.

Não vi classes internas usadas com muita frequência. A única coisa pela qual os vi usar é poder chamar um método privado da classe pai de fora do pai nos casos de Teste de Unidade. Algo assim:

  1. classe pública PrivateExample {private void doPrivate () {System.out.println ("método privado chamado"); } public class PrivateMethodAccess {public void callPrivate () {doPrivate (); }}} public class Tester {public static void main (String [] args) {PrivateExample pe = new PrivateExample (); PrivateExample.PrivateMethodAccess pma = pe.novo PrivateMethodAccess (); pma.callPrivate (); }}

Isso basicamente apenas expõe um método privado que praticamente derrota o propósito de ter o método privado em primeiro lugar.

Existem dois tipos de classes aninhadas. Estático e não estático. O não estático é chamado de classe interna.

A principal diferença entre eles é que, no caso de classe estática, ela pode ser instanciada sem ter que instanciar a classe externa, enquanto no caso de classe interna, não é possível e você deve ter uma instância de OuterClass.

Então, para instanciar a classe estática, você chamaria:

OuterClass.InnerClass ic = new OuterClass.InnerClass ();

mas para instanciar a classe interna (não estática), você teria que chamar:

  1. OuterClass ot = new OuterClass (); OuterClass.InnerClass ic = ot.novo InnerClass ();

A segunda diferença é que a classe interna estática tem acesso a membros estáticos da classe externa, enquanto a não-estática tem acesso a todos os membros, incluindo os não-estáticos.

Joshua Bloch tem um capítulo em Java eficaz que é um excelente guia para este tópico. Mas, geralmente, uma classe interna estática encapsularia alguma funcionalidade que a classe externa precisa, mas cada instância da classe externa não precisa de sua própria instância da classe interna. Uma classe interna não estática normalmente seria como um manipulador de eventos (que geralmente também é anônimo). Recentemente, tive ocasião de usar uma classe interna não-anônima e não-estática: adaptou um membro de instância de dados específico da classe externa usada como AbstractTableModel. Essa classe interna permaneceu abstrata para que eu pudesse concluir todas as outras coisas do modelo de tabela (como colunas etc.) em uma classe diferente, o que poderia representar os dados como uma JTable.

Quando você cria classes internas, elas obtêm referências à classe externa para que possam fazer o que quiserem com a classe externa. Uma classe aninhada estática é como uma classe regular.

Quando usar uma classe interna

Se você deseja ter uma lógica que afeta a classe externa, você deve fazer isso. Existem muitos casos de uso válidos para esse tipo de classe com qualquer modificador de acesso.

Quando usar uma classe aninhada estática

Se você não precisar de uma referência à classe externa, use isso. É isso que acabo usando a maior parte do tempo. Ele pode ser usado para agrupar várias variáveis ​​relacionadas e é melhor do que criar outra classe quando você deseja que ela seja privada. Se você está pensando em torná-lo público, talvez seja melhor criar outra classe, a menos que você tenha um bom motivo para mantê-la aninhada.

Uma classe interna só pode ser instanciada no contexto de uma instância da classe externa. Dentro da classe interna, você pode acessar os membros e métodos do objeto externo onde ele foi criado. Você usaria uma classe interna quando o objeto interno estiver fortemente vinculado a uma instância da sua classe externa.

Uma classe aninhada estática existe separadamente da classe circundante. A classe interna se comporta exatamente como uma classe de nível superior, exceto que o nome da classe seria OuterClass.InnerClass. Seu principal uso é indicar que ambas as classes têm um relacionamento muito estreito.

A principal diferença é que as classes internas têm acesso ao estado do objeto que contém, enquanto as classes aninhadas estáticas não. Na verdade, existem quatro tipos distintos de classe aninhada:

  • Classe aninhada estática: sem acesso ao objeto que contém, a menos que você faça uma referência a esse objeto (como uma classe não aninhada)
  • Classe interna: pode acessar o estado privado do objeto, por referência direta ou por OuterClassName.this.fieldName
  • Classe local: como uma classe interna, mas em vez de ser definida diretamente na classe externa, ela é definida dentro de um método e só tem acesso ao que estiver no escopo desse método, e esses campos / variáveis ​​devem ser finais
  • Classe interna anônima: como uma classe local, mas não tem nome e só está disponível no escopo em que está definida.

Quando você os usaria?

  • Classe aninhada estática: quando a classe é tão pequena (por exemplo, menos de 5 linhas) que não vale a pena ter seu próprio arquivo de origem; e / ou quando existe uma relação muito próxima entre a classe interna e externa. Por exemplo, se um campo na classe externa puder ter um intervalo limitado de valores, você poderá definir os valores em uma classe aninhada estática pública. (Desde que o Enum foi introduzido, tornou-se comum ter um Enum aninhado em público.) Portanto, o intervalo de valores em algum sentido "pertence" à classe externa.
  • Classe interna e local: existem muitos padrões que os utilizam; Um exemplo comum é a classificação: se houver várias maneiras de classificar sua classe, você poderá implementar cada uma delas como uma classe interna que implementa Comparable e entregar uma instância adequada a quem solicitar. Se a classe externa implementasse o Comparable, ela poderia implementar apenas uma única ordem de classificação. Classes interna e local quase sempre implementam pelo menos uma interface.
  • Classes internas anônimas: usadas para criar uma implementação de uma interface para uso em apenas um outro local (e na minha experiência, isso é mais comum do que o caso mais geral de classes internas / locais). De longe, o caso de uso mais comum são os manipuladores de eventos para o padrão Observer (também chamado de publicação-assinatura). Uma classe que é a fonte dos eventos permite que (vários) assinantes "se inscrevam" nos eventos passando um manipulador de eventos, que é adicionado a uma lista a ser chamada quando o evento acontece. O manipulador de eventos geralmente é uma classe interna anônima que implementa a interface apropriada.

Em geral, o que é bom nas classes aninhadas / internas é que elas aumentam

encapsulamento

. Em vez de passar toda a sua classe para outra pessoa (por exemplo, para classificação ou manipulação de eventos), você pode passar uma instância de uma classe muito menor e mais simples, geralmente uma que implemente alguma interface muito simples. Como o outro lado só conhece a interface simples, ele não pode chamar a maioria dos outros métodos da sua classe, portanto, há menos risco de

acoplamento

e muito menos chance de efeitos colaterais. É um bom design orientado a objetos.

Classe aninhada é basicamente uma classe incluída em outra classe. Uma classe aninhada não estática é uma classe interna. A razão pela qual usamos classes aninhadas é ter um agrupamento lógico de classes, que são usadas apenas entre si e ajuda a otimizar os pacotes também. Também implementa melhor o encapsulamento, por exemplo, considere duas classes Carro e Pneu. Agora, digamos que a classe Tire precise acessar alguma variável privada da classe Car, por exemplo wheelSpace, podemos incluir a classe Tire na classe Car, e ela obteria acesso às variáveis ​​privadas.

  1. Carro da classe {private double wheelSpace; Class Tire {// Verifique se a roda se encaixa no público booleano isWheelFit () {// Use o espaço da roda aqui.}}}

Aqui, a classe interna ou a classe aninhada não estática tem acesso direto às variáveis ​​da classe Outer.

A classe aninhada estática, por outro lado, não pode fazer referência direta às variáveis ​​de instância da classe externa; ela deve usar uma referência a objeto.

A principal diferença é que uma classe aninhada pode acessar os campos particulares de sua classe que o contém. Uma classe interna estática não pode.

Uma classe interna estática é mais normal nesse aspecto.

Prefiro classes internas estáticas e as uso para transmitir alguns objetos personalizados que são um detalhe de implementação puro e oculto da minha classe que os contém.

Costumo extrair> para o nível superior e tê-los como pacote privado.

Uma classe aninhada funciona mais como um fechamento de função em JavaScript e pode ser usada por razões semelhantes - principalmente retornos de chamada.

Ambos são bastante raros para mim. Você pode simplesmente escrever equivalentes de código mais simples e mais normais normalmente.