Java - classes internas

Neste capítulo, discutiremos as classes internas de Java.

Classes aninhadas

Em Java, assim como os métodos, as variáveis ​​de uma classe também podem ter outra classe como membro. Escrever uma classe dentro de outra é permitido em Java. A classe escrita dentro é chamada denested class, e a classe que contém a classe interna é chamada de outer class.

Syntax

A seguir está a sintaxe para escrever uma classe aninhada. Aqui a aulaOuter_Demo é a classe externa e a classe Inner_Demo é a classe aninhada.

class Outer_Demo {
   class Inner_Demo {
   }
}

As classes aninhadas são divididas em dois tipos -

  • Non-static nested classes - Esses são os membros não estáticos de uma classe.

  • Static nested classes - Esses são os membros estáticos de uma classe.

Classes internas (classes aninhadas não estáticas)

As classes internas são um mecanismo de segurança em Java. Sabemos que uma classe não pode ser associada ao modificador de acessoprivate, mas se tivermos a classe como membro de outra classe, a classe interna pode se tornar privada. E isso também é usado para acessar os membros privados de uma classe.

As classes internas são de três tipos, dependendo de como e onde você as define. Eles são -

  • Classe Interna
  • Classe interna local do método
  • Classe interna anônima

Classe Interna

Criar uma classe interna é bastante simples. Você só precisa escrever uma classe dentro de uma classe. Ao contrário de uma classe, uma classe interna pode ser privada e uma vez que você declara uma classe interna privada, ela não pode ser acessada de um objeto fora da classe.

A seguir está o programa para criar uma classe interna e acessá-la. No exemplo fornecido, tornamos a classe interna privada e acessamos a classe por meio de um método.

Example

class Outer_Demo {
   int num;
   
   // inner class
   private class Inner_Demo {
      public void print() {
         System.out.println("This is an inner class");
      }
   }
   
   // Accessing he inner class from the method within
   void display_Inner() {
      Inner_Demo inner = new Inner_Demo();
      inner.print();
   }
}
   
public class My_class {

   public static void main(String args[]) {
      // Instantiating the outer class 
      Outer_Demo outer = new Outer_Demo();
      
      // Accessing the display_Inner() method.
      outer.display_Inner();
   }
}

Aqui você pode observar que Outer_Demo é a classe externa, Inner_Demo é a classe interna, display_Inner() é o método dentro do qual estamos instanciando a classe interna, e este método é invocado a partir do main método.

Se você compilar e executar o programa acima, obterá o seguinte resultado -

Output

This is an inner class.

Acessando os membros privados

Conforme mencionado anteriormente, as classes internas também são usadas para acessar os membros privados de uma classe. Suponha que uma classe tenha membros privados para acessá-los. Escreva uma classe interna nele, retorne os membros privados de um método dentro da classe interna, digamos,getValue()e, finalmente, de outra classe (da qual você deseja acessar os membros privados), chame o método getValue () da classe interna.

Para instanciar a classe interna, inicialmente você deve instanciar a classe externa. Depois disso, usando o objeto da classe externa, a seguir está a maneira pela qual você pode instanciar a classe interna.

Outer_Demo outer = new Outer_Demo();
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();

O programa a seguir mostra como acessar os membros privados de uma classe usando a classe interna.

Example

class Outer_Demo {
   // private variable of the outer class
   private int num = 175;  
   
   // inner class
   public class Inner_Demo {
      public int getNum() {
         System.out.println("This is the getnum method of the inner class");
         return num;
      }
   }
}

public class My_class2 {

   public static void main(String args[]) {
      // Instantiating the outer class
      Outer_Demo outer = new Outer_Demo();
      
      // Instantiating the inner class
      Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
      System.out.println(inner.getNum());
   }
}

Se você compilar e executar o programa acima, obterá o seguinte resultado -

Output

This is the getnum method of the inner class: 175

Classe interna local do método

Em Java, podemos escrever uma classe dentro de um método e este será um tipo local. Como as variáveis ​​locais, o escopo da classe interna é restrito ao método.

Uma classe interna local de método pode ser instanciada apenas dentro do método em que a classe interna está definida. O programa a seguir mostra como usar uma classe interna local de método.

Example

public class Outerclass {
   // instance method of the outer class 
   void my_Method() {
      int num = 23;

      // method-local inner class
      class MethodInner_Demo {
         public void print() {
            System.out.println("This is method inner class "+num);	   
         }   
      } // end of inner class
	   
      // Accessing the inner class
      MethodInner_Demo inner = new MethodInner_Demo();
      inner.print();
   }
   
   public static void main(String args[]) {
      Outerclass outer = new Outerclass();
      outer.my_Method();	   	   
   }
}

Se você compilar e executar o programa acima, obterá o seguinte resultado -

Output

This is method inner class 23

Classe interna anônima

Uma classe interna declarada sem um nome de classe é conhecida como um anonymous inner class. No caso de classes internas anônimas, nós as declaramos e instanciamos ao mesmo tempo. Geralmente, eles são usados ​​sempre que você precisa substituir o método de uma classe ou interface. A sintaxe de uma classe interna anônima é a seguinte -

Syntax

AnonymousInner an_inner = new AnonymousInner() {
   public void my_method() {
      ........
      ........
   }   
};

O programa a seguir mostra como substituir o método de uma classe usando uma classe interna anônima.

Example

abstract class AnonymousInner {
   public abstract void mymethod();
}

public class Outer_class {

   public static void main(String args[]) {
      AnonymousInner inner = new AnonymousInner() {
         public void mymethod() {
            System.out.println("This is an example of anonymous inner class");
         }
      };
      inner.mymethod();	
   }
}

Se você compilar e executar o programa acima, obterá o seguinte resultado -

Output

This is an example of anonymous inner class

Da mesma forma, você pode substituir os métodos da classe concreta, bem como a interface, usando uma classe interna anônima.

Classe interna anônima como argumento

Geralmente, se um método aceita um objeto de uma interface, uma classe abstrata ou uma classe concreta, podemos implementar a interface, estender a classe abstrata e passar o objeto para o método. Se for uma classe, podemos passá-la diretamente para o método.

Mas em todos os três casos, você pode passar uma classe interna anônima para o método. Aqui está a sintaxe de passar uma classe interna anônima como um argumento de método -

obj.my_Method(new My_Class() {
   public void Do() {
      .....
      .....
   }
});

O programa a seguir mostra como passar uma classe interna anônima como um argumento de método.

Example

// interface
interface Message {
   String greet();
}

public class My_class {
   // method which accepts the object of interface Message
   public void displayMessage(Message m) {
      System.out.println(m.greet() +
         ", This is an example of anonymous inner class as an argument");  
   }

   public static void main(String args[]) {
      // Instantiating the class
      My_class obj = new My_class();

      // Passing an anonymous inner class as an argument
      obj.displayMessage(new Message() {
         public String greet() {
            return "Hello";
         }
      });
   }
}

Se você compilar e executar o programa acima, terá o seguinte resultado -

Output

Hello, This is an example of anonymous inner class as an argument

Classe Aninhada Estática

Uma classe interna estática é uma classe aninhada que é um membro estático da classe externa. Ele pode ser acessado sem instanciar a classe externa, usando outros membros estáticos. Assim como os membros estáticos, uma classe aninhada estática não tem acesso às variáveis ​​de instância e métodos da classe externa. A sintaxe da classe aninhada estática é a seguinte -

Syntax

class MyOuter {
   static class Nested_Demo {
   }
}

Instanciar uma classe aninhada estática é um pouco diferente de instanciar uma classe interna. O programa a seguir mostra como usar uma classe aninhada estática.

Example

public class Outer {
   static class Nested_Demo {
      public void my_method() {
         System.out.println("This is my nested class");
      }
   }
   
   public static void main(String args[]) {
      Outer.Nested_Demo nested = new Outer.Nested_Demo();	 
      nested.my_method();
   }
}

Se você compilar e executar o programa acima, obterá o seguinte resultado -

Output

This is my nested class