Clase interna en Java

En Java, la clase interna se refiere a la clase que se declara dentro de la clase o interfaz que se introdujo principalmente, para resumir, las mismas clases lógicamente relacionables ya que Java está puramente orientado a objetos, por lo que lo acerca al mundo real. Ahora, geeks, deben preguntarse por qué se introdujeron. 

Hay ciertas ventajas asociadas con las clases internas que son las siguientes:

  • Hacer código limpio y legible.
  • Se puede acceder a métodos privados de la clase externa, trayendo así una nueva dimensión y acercándola al mundo real.
  • Optimización del módulo de código.

Los usamos a menudo a medida que avanzamos en la programación orientada a objetos de Java donde queremos que se realicen ciertas operaciones, otorgando acceso a clases limitadas y muchas más, que quedarán claras a medida que analicemos e implementemos todo tipo de clases internas en Java.

Tipos de clases internas

Hay básicamente cuatro tipos de clases internas en Java.

  1. Clase interna anidada
  2. Método Clases Internas Locales
  3. Clases anidadas estáticas
  4. Clases internas anónimas

Analicemos cada uno de los siguientes tipos de forma secuencial en profundidad junto con un programa java limpio que es muy importante en cada paso, ya que se vuelve bastante complicado a medida que avanzamos.

Tipo 1: clase interna anidada 

Puede acceder a cualquier variable de instancia privada de la clase externa. Como cualquier otra variable de instancia, podemos tener un modificador de acceso privado, protegido, público y un modificador predeterminado. Al igual que la clase, una interfaz también se puede anidar y puede tener especificadores de acceso. 

Ejemplo 1A

Java

// Java Program to Demonstrate Nested class 
 
// Class 1
// Helper classes
class Outer {
 
    // Class 2
    // Simple nested inner class
    class Inner {
 
        // show() method of inner class
        public void show()
        {
 
            // Print statement
            System.out.println("In a nested class method");
        }
    }
}
 
// Class 2
// Main class
class Main {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Note how inner class object is created inside
        // main()
        Outer.Inner in = new Outer().new Inner();
 
        // Calling show() method over above object created
        in.show();
    }
}
Producción

In a nested class method

Nota:  No podemos tener un método estático en una clase interna anidada porque una clase interna está implícitamente asociada con un objeto de su clase externa, por lo que no puede definir ningún método estático por sí misma. Por ejemplo, el siguiente programa no compila. 

Ejemplo 1B

Java

// Java Program to Demonstrate Nested class 
// Where Error is thrown
 
// Class 1
// Outer class
class Outer {
 
    // Method defined inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Inner class
    class Inner {
 
        // Main driver method
        public static void main(String[] args)
        {
 
            // Display message for better readability
            System.out.println("inside inner class Method");
        }
    }
}

Producción:

Una interfaz también se puede anidar y las interfaces anidadas tienen algunas propiedades interesantes. Cubriremos las interfaces anidadas en la próxima publicación.

Tipo 2: Método Clases Internas Locales 

La clase interna se puede declarar dentro de un método de una clase externa que ilustraremos en el siguiente ejemplo, donde Inner es una clase interna en métodoexterno().

Ejemplo 1

Java

// Java Program to Illustrate Inner class can be
// declared within a method of outer class
 
// Class 1
// Outer class
class Outer {
 
    // Method inside outer class
    void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
 
        // Class 2
        // Inner class
        // It is local to outerMethod()
        class Inner {
 
            // Method defined inside inner class
            void innerMethod()
            {
 
                // Print statement whenever inner class is
                // called
                System.out.println("inside innerMethod");
            }
        }
 
        // Creating object of inner class
        Inner y = new Inner();
 
        // Calling over method defined inside it
        y.innerMethod();
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating object of outer class inside main()
        // method
        Outer x = new Outer();
 
        // Calling over the same method
        // as we did for inner class above
        x.outerMethod();
    }
}
Producción

inside outerMethod
inside innerMethod

Método Las clases internas locales no pueden usar una variable local del método externo hasta que esa variable local no se declare como final. Por ejemplo, el siguiente código genera un error de compilación. 

Nota: «x» no es final en el método externo() y el método interno() intenta acceder a él.

Ejemplo 2

Java

class Outer {
   void outerMethod() {
      int x = 98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x= "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
   public static void main(String[] args) {
      Outer x=new Outer();
      x.outerMethod();
   }
}
Producción

inside outerMethod
x= 98

Nota: la clase interna local no puede acceder a la variable local no final hasta JDK 1.7. Desde JDK 1.8, es posible acceder a la variable local no final en la clase interna local del método. 

Pero el siguiente código compila y funciona bien (Tenga en cuenta que x es definitivo esta vez) 

Ejemplo 3

Java

class Outer {
   void outerMethod() {
      final int x=98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x = "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
    public static void main(String[] args){
      Outer x = new Outer();
      x.outerMethod();
    }
}
Producción

inside outerMethod
x = 98

La razón principal por la que necesitamos declarar una variable local como final es que la variable local vive en la pila hasta que el método está en la pila, pero puede haber un caso en el que el objeto de la clase interna aún viva en el montón. 
La clase interna local del método no se puede marcar como privada, protegida, estática y transitoria, pero se puede marcar como abstracta y final, pero no ambas al mismo tiempo.

Tipo 3: Clases Anidadas Estáticas

Las clases anidadas estáticas no son técnicamente clases internas. Son como un miembro estático de la clase externa. 

Ejemplo

Java

// Java Program to Illustrate Static Nested Classes
 
// Importing required classes
import java.util.*;
 
// Class 1
// Outer class
class Outer {
 
    // Method
    private static void outerMethod()
    {
 
        // Print statement
        System.out.println("inside outerMethod");
    }
 
    // Class 2
    // Static inner class
    static class Inner {
 
        public static void display()
        {
 
            // Print statement
            System.out.println("inside inner class Method");
 
            // Calling method inside main() method
            outerMethod();
        }
    }
}
 
// Class 3
// Main class
class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        Outer.Inner obj = new Outer.Inner();
 
        // Calling method via above instance created
        obj.display();
    }
}
Producción

inside inner class Method
inside outerMethod

Tipo 4: Clases Internas Anónimas 

Las clases internas anónimas se declaran sin ningún nombre. Se crean de dos maneras. 

  • Como una subclase del tipo especificado
  • Como implementador de la interfaz especificada

Vía 1: como una subclase del tipo especificado 

Ejemplo:

Java

// Java Program to Illustrate Anonymous Inner classes
// Declaration Without any Name 
// As a subclass of the specified type
 
// Importing required classes
import java.util.*;
 
// Class 1
// Helper class
class Demo {
 
    // Method of helper class
    void show()
    {
        // Print statement
        System.out.println(
            "i am in show method of super class");
    }
}
 
// Class 2
// Main class
class Flavor1Demo {
 
    //  An anonymous class with Demo as base class
    static Demo d = new Demo() {
        // Method 1
        // show() method
        void show()
        {
            // Calling method show() via super keyword
            // which refers to parent class
            super.show();
 
            // Print statement
            System.out.println("i am in Flavor1Demo class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        d.show();
    }
}
Producción

i am in show method of super class
i am in Flavor1Demo class

En el código anterior, tenemos dos clases Demo y Flavor1Demo. Aquí la demostración actúa como una superclase y la clase anónima actúa como una subclase, ambas clases tienen un método show(). En la clase anónima, el método show() se anula.

Vía 2: como implementador de la interfaz especificada  

Ejemplo:

Java

// Java Program to Illustrate Anonymous Inner Classes
// Declaration Without Any Name
// As an implementer of Specified interface
 
// Interface
interface Hello {
 
    // Method defined inside interface
    void show();
}
 
// Main class
class GFG {
 
    // Class implementing interface
    static Hello h = new Hello() {
       
        // Method 1
        // show() method inside main class
        public void show()
        {
            // Print statement
            System.out.println("i am in anonymous class");
        }
    };
 
    // Method 2
    // Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        h.show();
    }
}
Producción

i am in anonymous class

Explicación de salida:

En el código anterior, creamos un objeto de clase interna anónima, pero esta clase interna anónima es un implementador de la interfaz Hola. Cualquier clase interna anónima puede implementar solo una interfaz a la vez. Puede extender una clase o implementar una interfaz a la vez.
Este artículo es una contribución de Pawan Kumar . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *