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

教程基础Java

Java Controllo di flusso

Java Array

Java Orientato agli oggetti (I)

Java Orientato agli oggetti (II)

Java Orientato agli oggetti (III)

Gestione delle eccezioni Java

Java List

Java Queue (coda)

Java Map collection

Java Set collection

Java Input/Output (I/O)

Java Reader/Writer

Altri argomenti Java

Classi annidate e classi interne Java

In questo tutorial, imparerai le classi annidate e i loro tipi in Java tramite esempi.

In Java, puoi definire una classe in un'altra classe. Questa classe è chiamata classe annidata (classe annidata). Ad esempio,

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

Puoi creare due tipi di classi annidate in Java.

  • Classe annidata non statica (classe interna)

  • Classe interna statica

Leggi correlate:

Iniziamo a guardare la classe annidata non statica.

Classe annidata non statica (classe interna)

La classe annidata non statica è una classe in un'altra classe. Ha il diritto di accedere ai membri della classe chiudente (classe esterna). Di solito viene chiamata classe interna (classe interna).

Poiché la classe interna esiste nella classe esterna, è necessario istanziare prima la classe esterna per istanziare la classe interna.

Questo è un esempio di come dichiarare una classe interna in Java.

Esempio 1: classe interna

class CPU {
    double price;
    // classe annidata
    class Processor {
        // membri della classe annidata
        double cores;
        String manufacturer;
        double getCache() {
            return 4.3;
        }
    }
    // classe annidata protetta
    protected class RAM {
        // membri della classe annidata protetta
        double memory;
        String manufacturer;
        double getClockSpeed() {
            return 5.5;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        // creazione dell'oggetto della classe esterna CPU
        CPU cpu = new CPU();
       // creazione dell'oggetto della classe interna Processor utilizzando la classe esterna
        CPU.Processor processor = cpu.new Processor();
        // creazione dell'oggetto della classe interna RAM utilizzando la classe esterna CPU
        CPU.RAM ram = cpu.new RAM();
        System.out.println("Processor Cache = " + processor.getCache());
        System.out.println("Ram Clock speed = " + ram.getClockSpeed());
    }
}

Output:

Processor Cache = 4.3
Ram Clock speed = 5.5

Nel programma sopra, ci sono due classi annidate: Processor e RAM all'interno della classe esterna CPU:. Possiamo dichiarare la classe interna come protetta. Pertanto, abbiamo dichiarato la classe RAM come protetta.

All'interno della classe Main

  • Prima di tutto, creiamo un'istanza della classe esterna CPU chiamata cpu.

  • Poi, utilizzando l'istanza della classe esterna, crea un oggetto della classe interna: 

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

Attenzione:Usiamo l'operatore di punto (.) per creare un'istanza della classe interna utilizzando la classe esterna.

Accesso ai membri della classe esterna nella classe interna

Possiamo utilizzare la chiave this per accedere ai membri della classe esterna. Se desideri sapere di più su questa chiave, visitaChiave this in Java。 

Esempio 2: accesso ai membri

class Car {
    String carName;
    String carType;
    // assegnazione valore tramite costruttore
    public Car(String name, String type) {
        this.carName = name;
        this.carType = type;
    }
    // privato metodo
    private String getCarName() {}}
        return this.carName;
    }
    //Classe interna
    class Engine {
        String engineType;
        void setEngine() {
           //Accesso all'attributo carType di Car
            if(Car.this.carType.equals("4WD")){
                //Chiamata al metodo getCarName() di Car
                if(Car.this.getCarName().equals("Crysler")) {
                    this.engineType = "Più piccolo";
                }
                    this.engineType = "Più grande";
                }
            }
                this.engineType = "Più grande";
            }
        }
        String getEngineType(){
            return this.engineType;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        //Creazione di un oggetto della classe esterna Car
        Car car1 = new Car("Mazda", "8WD");
        //Creazione di un oggetto della classe interna utilizzando la classe esterna
        Car.Engine engine = car1.new Engine();
        engine.setEngine();
        System.out.println("8WD tipo motore = " + engine.getEngineType());
        Car car2 = new Car("Crysler", "4WD");
        Car.Engine c2engine = car2.new Engine();
        c2engine.setEngine();
        System.out.println("4WD tipo motore = " + c2engine.getEngineType());
    }
}

Output:

8WD tipo motore = Più grande
4WD tipo motore = Più piccolo

Nel programma sopra, abbiamo una classe interna Engine nella classe esterna Car. Presta attenzione a questa riga,

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

Usiamo la parola chiave this per accedere alla variabile carType della classe esterna. Potresti aver notato che usiamo Car.this.carType invece di this.carType.

Questo è perché se non menzioniamo il nome della classe esterna Car, la parola chiave this rappresenta il membro della classe interna.

Anche noi possiamo accedere ai metodi della classe esterna dall'interno della classe interna.

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

Occorre notare che, anche se getCarName() è un metodo privato, possiamo accedervi dall'interno della classe interna.

Classe interna statica

In Java, possiamo definire anche una classe statica (static) all'interno di un'altra classe. Questo tipo di classe si chiama classe interna statica (static nested class). Le classi interne statiche non si chiamano classi interne statiche.

Diversamente dalle classi interne, le classi interne statiche non possono accedere agli attributi delle classi esterne. Questo è perchéClasse interna staticaNon è necessario creare un'istanza della classe esterna.

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

In questo caso, creiamo l'oggetto utilizzando solo il nome della classe esterna.Classe interna staticaPoiché l'oggetto è creato utilizzando solo il nome della classe esterna, non è possibile utilizzare OuterClass.this per riferirsi alla classe esterna.

Esempio 3: classe interna statica

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) {
       //创建静态嵌套类的对象
       //Utilizzo del nome della classe esterna
       MotherBoard.USB usb = new MotherBoard.USB();
       System.out.println("Total Ports = " + usb.getTotalPorts());
   }
}

Output:

Total Ports = 3

Nel programma sopra, abbiamo creato una classe statica chiamata USB all'interno della classe MotherBoard. Presta attenzione a questa riga:

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

In questo caso, creiamo un oggetto USB utilizzando il nome della classe esterna.

Ora, vediamo cosa accade se si tenta di accedere agli attributi di una classe esterna:

Esempio 4: accesso agli attributi di una classe esterna all'interno di una classe interna statica

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());
   }
}

Quando tentiamo di eseguire il programma, verrà visualizzato un errore:

errore: variabile non statica this non può essere riferita da un contesto statico

Questo è perché non stiamo utilizzando l'oggetto della classe esterna per creare l'oggetto della classe interna. Pertanto, non ci sono riferimenti memorizzati in Motherboard.this per la classe esterna Motherboard.

Punti da ricordare

  • Java considera le classi interne come membri regolari delle classi. Sono come i metodi e le variabili dichiarati all'interno della classe.

  • Poiché le classi interne sono membri della classe esterna, è possibile applicare qualsiasi modificatore di accesso (come private, protected) alle classi interne, il che non è possibile nelle classi normali.

  • Poiché le classi annidate sono membri della classe esterna, è possibile utilizzare la notazione punto (.) per accedere alle classi annidate e ai loro membri.

  • L'uso delle classi annidate renderà il codice più leggibile e fornirà una migliore astrazione.

  • Le classi annidate non statiche (classi interne) possono accedere agli altri membri della classe esterna/enclosing, anche se sono dichiarati come privati.