classes internas em java

significado da classe interna
como o nome indica, uma classe dentro de outra classe é chamada de classe interna.
as classes internas compartilham uma relação especial com a classe que contém, pois têm acesso a todos os membros da classe externa(mesmo private).Isso ocorre porque uma classe interna também é um membro da classe externa, assim como outros campos e métodos.
como uma classe interna é uma classe dentro de outra classe, ela também pode ser referida como uma classe aninhada.
tipos de classes internas
uma classe interna pode ser dos seguintes tipos.

  1. classe interna Normal ou Regular ou aninhada(normalmente referida como apenas classe interna)
  2. método classe interna Local.
  3. classe interna anônima.
  4. classe aninhada estática

1. Classe interna aninhada
esta seção examinará todos os detalhes de uma classe interna. Para simplificar, considere as seguintes classes

class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}

aqui exterior é a classe exterior e interior é a classe interior que está contido no interior exterior.

criando objeto de classe interna
uma classe interna está dentro de outra classe. A classe contendo é chamada de classe externa. Assim, uma classe interna não pode existir sem classe externa e o mesmo se aplica ao seu objeto(ou instância).Um objeto de classe interna não pode existir sem um objeto de classe externa.Isso significa que, para criar uma instância de classe interna, você precisa ter uma instância de classe externa.
assim, objeto de classe interna pode ser criado pelo método abaixo dado.

// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();

Como claro no exemplo, para criar um objeto de classe interna, um objeto de classe externa é necessário.
há também um método de mão curta para criar objeto de classe interna.

Inner innerObject = new Outer().new Inner();

este método também requer objeto de classe externa.
apenas Remember….An objeto de classe interna não pode ser criado sem um objeto de seu contendo (ou classe externa).

criando objeto de classe interna dentro da classe externa
exemplo anterior assume que você está instanciando classe interna de algum lugar fora da classe externa.
mas, na maioria dos casos, um objeto de classe interna é necessário apenas dentro da classe externa, uma vez que a classe externa faz uso da classe interna.
então, como criamos um objeto de classe interna de classe externa interna?
considere a classe de amostra modificada abaixo.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; }}

observe a linha Inner innerObject = new Inner();.
anteriormente, foi declarado que um objeto de classe interna não pode ser criado sem um objeto de classe externa, mas o trecho de código acima está fazendo isso. Confuso !!!!
a sintaxe acima é válida porque é escrita dentro de um método de classe externa.
quando este código está sendo executado, já existe uma instância de classe externa presente, que está executando o método.

lembre-se sempre, para criar(ou acessar) um objeto de classe interna, deve haver uma instância de classe externa.

Para resumir,

  1. quando um objeto de classe interna é criado de dentro da classe externa, ele pode ser criado diretamente como Inner innerObject = new Inner();.
  2. quando um objeto de classe interna é criado de fora da classe externa, ele precisa ser criado como Inner innerObject = new Outer().new Inner();.

quando objetos de classe externa e interna são impressos, a seguir está a saída gerada:

instância de classe externa: instância de classe interna Outer@659e0bfd
: Outer $ Inner @ 2a139a55

Referenciando instância de classe externa, campos e métodos da classe interna
uma classe interna também é um membro de sua classe contendo como outros campos e métodos.
assim, ele pode acessar outros campos e métodos de classe externa da mesma forma que outros campos e métodos acessam um ao outro, diretamente.
isso é verdadeiro ao acessar campos e métodos de classe externa da classe interna.

mas, ao referir a instância da classe externa, há uma diferença. Para fazer referência à instância atual de uma classe, this palavra-chave é usada.
no caso da classe interna, usar this dentro da classe interna refere-se à instância atual da classe interna e não à sua classe externa.
para referenciar a instância da classe externa da classe interna, precisamos adicionar o nome da classe à palavra-chave this.

assim, para referenciar a instância de classe externa da classe interna, use Outer.this sintaxe.
consulte o exemplo abaixo para entender.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; public innerClassMethod() { // access outer class field System.out.println("Outer field : " + outerField); // access inner class instance System.out.println("Inner instance : " + this); // access outer class instance System.out.println("Outer instance : " + Outer.this); } }}

saída

campo externo: externo
instância interna:
instância externa:

2. Método classe interna Local
como o nome sugere, uma classe definida dentro de um método é um método classe interna Local.
Sim, é possível.
você pode definir uma classe dentro de um método como mostrado abaixo.

// outer classclass Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class"); } } // inner class ends } // method ends}

o código acima tem uma classe externa contendo um método.
este método define uma classe que está dentro do corpo do método, portanto chamada de classe interna local do método.
observe que a classe interna também tem sua própria definição de método.

instanciar um método classe interna local
o código anterior declara um método classe interna local, mas não cria nenhum objeto de classe interna.
agora surge a questão, como criar um objeto de método classe interna local.
como um método de classe interna local é definido dentro de um método, ele é visível apenas dentro desse método e seu objeto também pode ser criado apenas dentro desse método.
o código abaixo cria um objeto de classe interna local do método e chama seu método.

// outer classpublic class Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class method called"); } } // inner class ends // create inner class object Inner innerObject = new Inner(); // call inner class method innerObject.innerMethod(); } // outer class method ends // Main method public static void main(String args) { // create object of outer class Outer outerObject = new Outer(); // call outer class method outerObject.createClass(); }}

Quando o código acima é executado, é o seguinte saída

Método local interior método de classe chamado

Isso mostra que quando o exterior método da classe for chamado, ele cria um objeto da classe interna e chama a classe interna de método.

método classe interna Local: pontos para lembrar
instrução que cria um objeto de método classe interna local deve ser escrita fora do corpo da classe.
assim, a linha Inner innerObject = new Inner(); deve vir após o término da classe local.

  1. um método de classe interna local pode ser instanciado apenas dentro do método em que é declarado.
    isso faz sentido, pois uma classe de método é visível apenas dentro do método, portanto, seu objeto pode ser criado apenas dentro desse método.
  2. um método de classe interna local não pode acessar as variáveis locais do método em que é declarado.
    se precisar acessá-los, eles devem ser marcados final.
    isso é aplicável antes do java 8.
  3. você não pode acessar uma variável local de método dentro de uma classe interna local de método e, em seguida, atribuí-la novamente. Este será um erro do compilador.
    isso é aplicável a partir do java 8, uma vez que as versões anteriores ao java 8 nem mesmo permitirão que você acesse uma variável local de método dentro da classe interna.
  4. um método classe interna local pode acessar os campos e outros métodos da classe aos quais o método que contém classe interna pertence.
  5. um método classe interna local pode acessar os campos static e outros métodos staticda classe A que o método que contém classe interna pertence apenas quando o método que contém é static.

3. Classes internas anônimas
significa anônimo cujo nome não é conhecido. No contexto do java, Uma classe anônima é aquela que não tem nome.
o termo classe anônima é aplicável apenas às classes internas, uma vez que as classes externas devem ter um nome.
uma classe anônima é uma classe interna porque sempre será definida dentro de outra classe.

tipos de classe anônima em java
na verdade, uma classe anônima é uma implementação de uma classe já existente ou uma interface que é escrita em outro lugar, mas é definida novamente dentro de outra classe, conforme necessário.
isso pode parecer confuso, mas os exemplos a seguir esclarecerão o conceito.

com base no fato de A classe anônima ser uma implementação de uma classe ou uma interface, ela pode pertencer a duas categorias a seguir

A. Subclasse de uma classe
vamos começar com um exemplo primeiro

// Already existing classclass Website {public void printName() {System.out.println("No website till now");}}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } };}

no exemplo acima, há uma classe chamada Website que já foi criada.
outra classe SearchEngine redefine esta classe, implementa seu método e atribui-lo a uma variável de referência que é do mesmo tipo que a classe real.
também é possível chamar o método recém-implementado usando esta variável de referência.

lembre-se de que a classe anônima recém-implementada é uma subclasse da classe real.
segue o polimorfismo e seu objeto pode ser passado em qualquer lugar que o objeto da classe Website seja esperado.
passe pelo exemplo abaixo para ilustração.

class Website { public void printName() { System.out.println("No website till now"); }}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of Website class public void getWebsite(Website web) { // call the method of Website class web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of Website class obj.getWebsite(obj.w); }}

em vez de pré-definir a implementação da classe Website, ela pode ser definida quando necessário, ou seja, ao chamar o método getWebsite.
assim, o método principal pode ser modificado como

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of Website class as argument obj.getWebsite(new Website() { public void print() { System.out.println("Dynamic implementation"); } });}

a implementação acima não é atribuída a nenhuma variável de referência, não tem nome e, portanto, o nome anônimo.

não é necessário que ambas as classes estejam no mesmo arquivo ou pacote. Eles podem ser localizados em qualquer lugar em relação um ao outro.

B. Implementador de Interface
uma classe anônima também pode ser definida como o implementador de uma interface.
nesse caso, ele definirá a implementação dos métodos declarados na interface e poderá ser passado em qualquer lugar em que o objeto da interface seja esperado.
consulte o exemplo abaixo para deixar claro.

interface WebInterface { // interface method declaration public void print();}class SearchEngine { // Notice the syntax WebInterface w = new WebInterface() { // Interface method implementation public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of WebInterface interface public void getWebsite(WebInterface web) { // call the method of WebInterface web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of WebInterface obj.getWebsite(obj.w); }}

Como antes, a implementação da interface como classe anônima pode ser criada quando necessário, conforme mostrado abaixo.

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of WebInterface as argument obj.getWebsite(new WebInterface() { public void print() { System.out.println("Dynamic implementation"); } });}
observe o uso da palavra-chave new antes do nome da interface. A classe anônima é o único lugar onde é possível.

polimorfismo em classes anônimas
conforme declarado anteriormente, classes anônimas seguem o polimorfismo.
como são subclasses, devem seguir o polimorfismo. Esta seção detalhará como.
considere a classe abaixo.

class Metal { public void printThickness() { System.out.println("Thick enough"); }}class MetalDriver { // Anonymous class definition Metal metal = new Metal() { public void printThickness() { System.out.println("Thick enough"); } // new method public boolean hasLustre() { return false; } }; public void printMetalDetail(Metal m) { // call method present in actual class definition. No problem!!! m.printThickness(); // call newly defined method in Anonymous class. Compiler Error!!! m.hasLustre(); }}

o código acima define uma classe Metal com um único método.
esta classe é implementada novamente anonimamente em outra classe MetalDriver onde um novo método é adicionado à sua definição que não está presente na classe real.

agora, quando este novo método é chamado, o compilador reclama com um erro

o método hasLustre() é indefinido para o tipo Metal.

Isso ocorre porque a classe anônima é uma subclasse enquanto a referência é da classe real(que é o pai).
o compilador não conseguiu encontrar o novo método na classe pai e sinaliza um erro.

assim, o erro estabelece dois fatos:
(I) A classe anônima é uma subclasse da classe real e
(ii) as definições de classe anônima seguem o polimorfismo.

uso de classe anônima
suponha que você precise chamar um método que leva um argumento de um tipo que é uma interface.
Agora, esta interface pertence a alguma biblioteca externa e você não tem uma classe que implementa esta interface.
como você chamará esse método. Se você passar null, existe o risco de exceções de tempo de execução.
classe anônima para o resgate.
Agora você pode criar uma classe anônima que implementa essa interface e passá-la pelo método que fornece a implementação de seus métodos de acordo com suas necessidades.
exemplo segue.

// Interface from external Libraryinterface External { public void interfaceMethod();}class CalledClass { // Method to called. Takes an argument of interface type public void toBeCalled(External e) { e.interfaceMethod(); }}

o código acima tem uma interface com um único método e uma classe cujo método você precisa chamar do seu código.

método desta classe leva um argumento de interface de tipo, mas você não tem uma classe que implementa esta interface.
se você passar null para o argumento do método, ele lançará imediatamente um java.lang.NullPointerException.
veja como você pode chamar esse método usando a classe Anonymous.

class CallingClass { // Main method public static void main(String args) { CalledClass obj = new CalledClass(); // call method using Anonymous class obj.toBeCalled(new External() { public void interfaceMethod() { // your code } }); }}

observe o uso da implementação de interface anônima para chamar o método.
este é o maior benefício das aulas anônimas.
4. Classe aninhada estática
uma classe estática que é definida dentro de outra classe é uma classe aninhada estática. É definido como uma classe normal precedida de palavra-chave estática.Lembre-se de que não há nada como classe estática, uma classe aninhada estática é apenas um membro estático de sua classe externa.
como é um membro estático, a seguir se aplica a uma classe aninhada estática.

  1. pode ser acessado pela classe externa diretamente sem ter sua instância.
  2. ele só pode acessar membros estáticos de sua classe externa, mas não suas variáveis ou métodos de instância.

exemplo de classe aninhada estática

public class Outer { // static nested class static class Inner { public void innerMethod() { System.out.println("Method of static nested class"); } } public void outerMethod() { System.out.println("Method of outer class"); } public static void main(String args) { // access inner class directly Inner inner = new Inner(); // call nested class method inner.innerMethod(); }}

Como você pode ver no exemplo acima, para acessar a classe aninhada estática, uma instância de classe externa não é necessária e pode ser acessada diretamente.
observe que o objeto da classe aninhada estática não pode acessar membros não estáticos da classe externa. No exemplo acima, a instância de classe aninhada não pode invocar outerMethod da classe externa.

vamos ajustar em

  1. quando uma classe contendo classe interna é compilada, então 2 arquivos de classe são gerados :
    um para classe externa e um para classe interna.
    Exemplo, Exterior.Classe E Exterior $ Interior.classe para classe externa classe externa e interna interna, respectivamente..
  2. o arquivo de classe da classe interna não pode ser executado diretamente usando o comando java.
  3. uma classe interna normal não pode ter static membros ou métodos de dados.
  4. uma classe interna pode ter um construtor.
  5. uma classe local de método pode ser instanciada apenas dentro do método em que é definido.
  6. uma classe local de método definida no método static pode acessar apenas static membros da classe envolvente.
  7. uma classe anônima que implementa uma interface, pode implementar apenas uma interface em oposição às classes normais que podem implementar muitos.
  8. uma classe anônima não pode estender uma classe e implementar uma interface ao mesmo tempo que as classes normais podem.
  9. definições de classe anônimas terminam com}; (observe os dois pontos).
  10. classes anônimas que são definidas como um argumento ao chamar um método end with }); (observe os dois pontos).
  11. você não pode chamar um método na referência de classe anônima que não está presente na classe real.
  12. uma classe interna precedida por static é conhecida como uma classe aninhada, não uma classe interna.

Leave a Reply