Java - clases internas

En este capítulo, discutiremos las clases internas de Java.

Clases anidadas

En Java, al igual que los métodos, las variables de una clase también pueden tener otra clase como miembro. Escribir una clase dentro de otra está permitido en Java. La clase escrita dentro se llamanested class, y la clase que contiene la clase interna se llama outer class.

Syntax

A continuación se muestra la sintaxis para escribir una clase anidada. Aqui la claseOuter_Demo es la clase externa y la clase Inner_Demo es la clase anidada.

class Outer_Demo {
   class Inner_Demo {
   }
}

Las clases anidadas se dividen en dos tipos:

  • Non-static nested classes - Estos son los miembros no estáticos de una clase.

  • Static nested classes - Estos son los miembros estáticos de una clase.

Clases internas (clases anidadas no estáticas)

Las clases internas son un mecanismo de seguridad en Java. Sabemos que una clase no se puede asociar con el modificador de acceso.private, pero si tenemos la clase como miembro de otra clase, entonces la clase interna puede hacerse privada. Y esto también se usa para acceder a los miembros privados de una clase.

Las clases internas son de tres tipos dependiendo de cómo y dónde las defina. Ellos son -

  • Clase interior
  • Clase interna de método local
  • Clase interna anónima

Clase interior

Crear una clase interna es bastante simple. Solo necesitas escribir una clase dentro de una clase. A diferencia de una clase, una clase interna puede ser privada y una vez que declaras privada una clase interna, no se puede acceder a ella desde un objeto fuera de la clase.

A continuación se muestra el programa para crear una clase interna y acceder a ella. En el ejemplo dado, hacemos que la clase interna sea privada y accedemos a la clase a través de un 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();
   }
}

Aquí puedes observar que Outer_Demo es la clase externa, Inner_Demo es la clase interior, display_Inner() es el método dentro del cual estamos instanciando la clase interna, y este método se invoca desde el main método.

Si compila y ejecuta el programa anterior, obtendrá el siguiente resultado:

Output

This is an inner class.

Accediendo a los miembros privados

Como se mencionó anteriormente, las clases internas también se utilizan para acceder a los miembros privados de una clase. Supongamos que una clase tiene miembros privados para acceder a ellos. Escriba una clase interna en ella, devuelva los miembros privados de un método dentro de la clase interna, digamos,getValue(), y finalmente desde otra clase (desde la que desea acceder a los miembros privados) llame al método getValue () de la clase interna.

Para crear una instancia de la clase interna, inicialmente debe crear una instancia de la clase externa. A partir de entonces, utilizando el objeto de la clase externa, la siguiente es la forma en que puede crear una instancia de la clase interna.

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

El siguiente programa muestra cómo acceder a los miembros privados de una clase usando la clase 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());
   }
}

Si compila y ejecuta el programa anterior, obtendrá el siguiente resultado:

Output

This is the getnum method of the inner class: 175

Clase interna de método local

En Java, podemos escribir una clase dentro de un método y este será un tipo local. Al igual que las variables locales, el alcance de la clase interna está restringido dentro del método.

Una clase interna local de método se puede instanciar solo dentro del método donde se define la clase interna. El siguiente programa muestra cómo utilizar una clase 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();	   	   
   }
}

Si compila y ejecuta el programa anterior, obtendrá el siguiente resultado:

Output

This is method inner class 23

Clase interna anónima

Una clase interna declarada sin un nombre de clase se conoce como anonymous inner class. En el caso de clases internas anónimas, las declaramos y las instanciamos al mismo tiempo. Generalmente, se utilizan siempre que necesite anular el método de una clase o interfaz. La sintaxis de una clase interna anónima es la siguiente:

Syntax

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

El siguiente programa muestra cómo anular el método de una clase usando una clase 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();	
   }
}

Si compila y ejecuta el programa anterior, obtendrá el siguiente resultado:

Output

This is an example of anonymous inner class

De la misma manera, puede anular los métodos de la clase concreta, así como la interfaz, utilizando una clase interna anónima.

Clase interna anónima como argumento

Generalmente, si un método acepta un objeto de una interfaz, una clase abstracta o una clase concreta, entonces podemos implementar la interfaz, extender la clase abstracta y pasar el objeto al método. Si es una clase, podemos pasarla directamente al método.

Pero en los tres casos, puede pasar una clase interna anónima al método. Aquí está la sintaxis de pasar una clase interna anónima como argumento de método:

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

El siguiente programa muestra cómo pasar una clase interna anónima como 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";
         }
      });
   }
}

Si compila y ejecuta el programa anterior, le da el siguiente resultado:

Output

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

Clase anidada estática

Una clase interna estática es una clase anidada que es un miembro estático de la clase externa. Se puede acceder sin instanciar la clase externa, utilizando otros miembros estáticos. Al igual que los miembros estáticos, una clase anidada estática no tiene acceso a las variables de instancia ni a los métodos de la clase externa. La sintaxis de la clase anidada estática es la siguiente:

Syntax

class MyOuter {
   static class Nested_Demo {
   }
}

Crear una instancia de una clase anidada estática es un poco diferente de crear una instancia de una clase interna. El siguiente programa muestra cómo utilizar una clase anidada 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();
   }
}

Si compila y ejecuta el programa anterior, obtendrá el siguiente resultado:

Output

This is my nested class