English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Java

Control de flujo Java

Java Arreglo

Java Programación Orientada a Objetos (I)

Java Programación Orientada a Objetos (II)

Java Programación Orientada a Objetos (III)

Manejo de excepciones en Java

Java Lista (List)

Java Queue (cola)

Colecciones de Java Map

Conjuntos de Java

Java Entrada/Salida (I/O)

Lector de Java/Writer

Temas de Java

Clases anidadas y clases internas de Java

En este tutorial, aprenderás sobre las clases anidadas en Java y sus tipos a través de ejemplos.

En Java, puedes definir una clase dentro de otra clase. Este tipo de clase se llama nested class (clase anidada). Por ejemplo,

class OuterClass {
    // ...
    class NestedClass {
        // ...
    }
}

Puede crear dos tipos de clases anidadas usando Java.

  • Clase interna no estática (clase interna)

  • 静态嵌套类

Lecturas relacionadas:

Veamos primero la clase interna no estática.

Clase interna no estática (clase interna)

La clase interna no está estática es otra clase dentro de una clase. Tiene derechos de acceso a los miembros de la clase encerrada (clase externa). Generalmente se llama inner class (clase interna).

Dado que la clase interna existe dentro de la clase externa, debe instanciar primero la clase externa para poder instanciar la clase interna.

Este es un ejemplo de cómo declarar una clase interna en Java.

示例1:clase interna

class CPU {
    double price;
    // Clase interna
    class Processor{
        //Miembros de la clase interna
        double cores;
        String manufacturer;
        double getCache(){
            return 4.3;
        }
    }
    //Clase interna protegida anidada
    protected class RAM{
        //Miembros de la clase interna protegida
        double memory;
        String manufacturer;
        double getClockSpeed(){
            return 5.5;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        //Crear un objeto de la clase externa CPU
        CPU cpu = new CPU();
       //Crear un objeto de la clase interna Processor usando la clase externa
        CPU.Processor processor = cpu.new Processor();
        //Crear un objeto de la clase interna RAM usando la clase externa CPU
        CPU.RAM ram = cpu.new RAM();
        System.out.println("Processor Cache = "); + processor.getCache());
        System.out.println("Ram Clock speed = "); + ram.getClockSpeed());
    }
}

输出:

Processor Cache = 4.3
Ram Clock speed = 5.5

En el programa anterior, hay dos clases anidadas: Processor y RAM dentro de la clase externa CPU:. Podemos declarar la clase interna como protegida. Por lo tanto, hemos declarado la clase RAM como protegida.

Dentro de la clase Main

  • Primero creamos una instancia de la clase externa CPU con el nombre cpu.

  • Luego, usando la instancia de la clase externa, creamos un objeto de la clase interna: 

    CPU.Processor processor = cpu.new Processor();
    CPU.RAM ram = cpu.new RAM();

Atención:Usamos el operador de punto (.) para crear una instancia de la clase interna desde la clase externa.

Acceder a los miembros de la clase externa en la clase interna

Podemos usar la palabra clave this para acceder a los miembros de la clase externa. Si desea obtener más información sobre esta palabra clave, por favor visiteLa palabra clave this en Java。}} 

示例2:Acceder a miembros

class Car {
    String carName;
    String carType;
    //Asignación de valor usando constructor
    public Car(String name, String type) {
        this.carName = name;
        this.carType = type;
    }
    // Método privado
    private String getCarName() {
        return this.carName;
    }
    //Clase interna
    class Engine {
        String engineType;
        void setEngine() {
           //Acceder al atributo carType de Car
            if(Car.this.carType.equals("4WD")){
                //Llamar al método getCarName() de Car
                if(Car.this.getCarName().equals("Crysler")) {
                    this.engineType = "Smaller";
                }
                    this.engineType = "Bigger";
                }
            }
                this.engineType = "Bigger";
            }
        }
        String getEngineType(){
            return this.engineType;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        //Crear un objeto de la clase externa Car
        Car car1 = new Car("Mazda", "8WD");
        //Crear un objeto de clase interna usando la clase externa
        Car.Engine engine = car1.new Engine();
        engine.setEngine();
        System.out.println("8WD tipo de motor = " + engine.getEngineType());
        Car car2 = new Car("Crysler", "4WD");
        Car.Engine c2engine = car2.new Engine();
        c2engine.setEngine();
        System.out.println("4WD tipo de motor = " + c2engine.getEngineType());
    }
}

输出:

8WD tipo de motor = Bigger
4WD tipo de motor = Smaller

En el programa anterior, tenemos una clase interna llamada Engine en la clase externa Car. Aquí, presta atención a esta línea,

if(Car.this.carType.equals("4WD")) { ... }

Usamos la palabra clave this para acceder a la variable carType de la clase externa. Puede que ya hayas notado que se usa Car.this.carType en lugar de this.carType.

Esto se debe a que si no mencionamos el nombre de la clase externa Car, la palabra clave this indicará el miembro de la clase interna.

同样,我们也从内部类访问外部类的方法。

if (Car.this.getCarName().equals("Crysler") {...

需要注意的是,尽管getCarName()是一个private方法,但我们能够从内部类访问它。

静态嵌套类

在Java中,我们还可以在另一个类中定义一个静态(static)类。 这种类称为静态嵌套类(static nested class)。 静态嵌套类不称为静态内部类。

与内部类不同,静态嵌套类无法访问外部类的成员变量。这是因为静态嵌套类不需要您创建外部类的实例。

OuterClass.NestedClass obj = new OuterClass.NestedClass();

在这里,我们仅通过使用外部类的类名来创建静态嵌套类的对象。因此,不能使用OuterClass.this引用外部类。

示例3:静态内部类

class MotherBoard {
   //静态嵌套类
   static class USB{
       int usb2 = 2;
       int usb3 = 1;
       int getTotalPorts(){
           return usb2 + usb3;
       }
   }
}
public class Main {
   public static void main(String[] args) {
       //创建静态嵌套类的对象
       //使用外部类的名称
       MotherBoard.USB usb = new MotherBoard.USB();
       System.out.println("Total Ports = ", + usb.getTotalPorts());
   }
}

输出:

Total Ports = 3

在上面的程序中,我们在类MotherBoard中创建了一个名为USB的静态类。 注意这一行,

MotherBoard.USB usb = new MotherBoard.USB();

在这里,我们使用外部类的名称创建一个USB对象。

现在,让我们看看如果尝试访问外部类的成员会发生什么:

示例4:在静态内部类内部访问外部类的成员

class MotherBoard {
   String model;
   public MotherBoard(String model) {
       this.model = model;
   }
   //静态嵌套类
   static class USB{
       int usb2 = 2;
       int usb3 = 1;
       int getTotalPorts(){
           //访问外部类的变量model
           if(MotherBoard.this.model.equals("MSI")) {
               return 4;
           }
           else {
               return usb2 + usb3;
           }
       }
   }
}
public class Main {
   public static void main(String[] args) {
       //创建静态嵌套类的对象
       MotherBoard.USB usb = new MotherBoard.USB();
       System.out.println("Total Ports = ", + usb.getTotalPorts());
   }
}

Cuando intentamos ejecutar el programa, se producirá un error:

error: non-variable estática this no se puede referenciar desde un contexto estático

Esto se debe a que no estamos utilizando el objeto de la clase externa para crear objetos de la clase interna. Por lo tanto, no hay referencia almacenada en Motherboard.this de la clase externa Motherboard.

Puntos a recordar

  • Java considera las clases internas como miembros regulares de la clase. Son como métodos y variables declarados dentro de la clase.

  • Dado que las clases internas son miembros de la clase externa, se puede aplicar cualquier modificador de acceso (como private, protected) a las clases internas, lo que no es posible en clases normales.

  • Dado que las clases anidadas son miembros de la clase externa, puede usar la notación de punto (.) para acceder a las clases anidadas y sus miembros.

  • El uso de clases anidadas hará que su código sea más legible y ofrezca mejor encapsulación.

  • Las clases anidadas no estáticas (clases internas) pueden acceder al exterior/Los otros miembros de la clase cerrada, incluso si se declaran como privados, también son así.