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

Основной учебник Java

Java Управление потоком

Java Массив

Java Ориентированность на объекты (I)

Java Ориентированность на объекты (II)

Java Ориентированность на объекты (III)

Обработка исключений Java

Java Список (List)

Java Queue (очередь)

Java Map коллекция

Java Set коллекция

Java Вход/Выход (I/O)

Java Reader/Writer

Другие темы Java

Вложенные и внутренние классы Java

В этом руководстве вы изучите вложенные классы в Java с помощью примеров и их типы.

В Java вы можете определить класс в другом классе. Such class is called nested class (вложенный класс). Например,

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

Вы можете создать два типа вложенных классов с помощью Java.

  • Не静电ное вложенное классы (внутренний класс)

  • Статическое вместилище класса

См. также:

Давайте начнем с не静电ного вложенного класса.

Не静电ное вложенное классы (внутренний класс)

Не静电ное вложенное классы - это класс в другом классе. Он имеет доступ к членам заключенного класса (внешнего класса). Обычно его называют inner class (внутренний класс).

Поскольку внутренний класс существует в классе-оболочке (внешний класс), его необходимо сначала инстанцировать, чтобы инстанцировать внутренний класс.

Это пример того, как можно объявить внутренний класс в Java.

Пример 1: внутренний класс

class CPU {
    double price;
    // вложенный класс
    class Processor {
        // члены вложенного класса
        double cores;
        String manufacturer;
        double getCache() {
            return 4.3;
        }
    }
    // вложенный класс с ограниченным доступом
    protected class RAM {
        // члены вложенного класса с ограниченным доступом
        double memory;
        String manufacturer;
        double getClockSpeed() {
            return 5.5;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        // создание объекта внешнего класса CPU
        CPU cpu = new CPU();
       // создание объекта внутреннего класса Processor с помощью внешнего класса
        CPU.Processor processor = cpu.new Processor();
        // создание объекта внутреннего класса RAM с помощью внешнего класса CPU
        CPU.RAM ram = cpu.new RAM();
        System.out.println("Processor cache = " + processor.getCache());
        System.out.println("Ram clockSpeed = " + ram.getClockSpeed());
    }
}

Вывод:

Processor cache = 4.3
Ram clockSpeed = 5.5

В вышеуказанном коде есть два вложенных класса: Processor и RAM в составе внешнего класса CPU:. Мы можем объявить внутренние классы как защищенные. Таким образом, мы объявили класс RAM как защищенный.

В классе Main

  • Сначала создаем экземпляр внешнего класса CPU с именем cpu.

  • Затем, используя экземпляр внешнего класса, создаем объект внутреннего класса: 

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

Внимание: мы используем оператор точки (.) для создания экземпляра внутреннего класса из внешнего класса.

Доступ к членам внешнего класса из внутреннего класса

Мы можем использовать ключевое слово this для доступа к членам внешнего класса. Если вы хотите узнать больше о данном ключе, пожалуйста, обратитесь кКлючевое слово this в Java. 

Пример 2: доступ к членам

class Car {
    String carName;
    String carType;
    // использование конструктора для назначения значений
    public Car(String name, String type) {
        this.carName = name;
        this.carType = type;
    }
    // private метод
    private String getCarName() {}}
        return this.carName;
    }
    //Внутренний класс
    class Engine {
        String engineType;
        void setEngine() {
           //Доступ к свойству carType класса Car
            if(Car.this.carType.equals("4WD")){
                //Вызов метода getCarName() класса 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) {
        //Создание объекта внешнего класса Car
        Car car1 = new Car("Mazda", "8WD");
        //Использование внешнего класса для создания объекта внутреннего класса
        Car.Engine engine = car1.new Engine();
        engine.setEngine();
        System.out.println("Тип двигателя 8WD = " + engine.getEngineType());
        Car car2 = new Car("Crysler", "4WD");
        Car.Engine c2engine = car2.new Engine();
        c2engine.setEngine();
        System.out.println("Тип двигателя 4WD = " + c2engine.getEngineType());
    }
}

Вывод:

Тип двигателя 8WD = Больше
Тип двигателя 4WD = Меньше

В предыдущем примере у нас есть внутренний класс Engine в классе Car. Обратите внимание на эту строку,

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

Мы используем ключевое слово this для доступа к переменной carType внешнего класса. Вы, возможно, уже заметили, что мы используем Car.this.carType вместо this.carType.

Это потому что, если мы не упоминаем имя внешнего класса Car, то ключевое слово this будет указывать на член внутреннего класса.

Так же, мы также доступываем методы внешнего класса из внутреннего класса.

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

Следует отметить, что, несмотря на то, что getCarName() является частным методом, мы можем доступа к нему из внутреннего класса.

Статическое вместилище класса

В 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("Общее количество портов = " + usb.getTotalPorts());
   }
}

Вывод:

Общее количество портов = 3

В上面的 программе, мы создали статический класс USB в классе MotherBoard. Обратите внимание на эту строку,

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("Общее количество портов = " + usb.getTotalPorts());
   }
}

Когда мы пытаемся запустить этот程序, появится ошибка:

ошибка: нестатическая переменная this не может бытьreferenced из статического контекста

Это потому, что мы не используем объект внешнего класса для создания объекта внутреннего класса. Таким образом, нет ссылки на внешний класс Motherboard, хранящуюся в Motherboard.this.

Важно помнить

  • Java рассматривает внутренние классы как обычных членов класса. Они такие же, как методы и переменные, объявленные в классе.

  • Поскольку внутренние классы являются членами внешнего класса, к внутренним классам можно применить любые модификаторы доступа (например, private, protected), что невозможно в обычных классах.

  • Поскольку вложенные классы являются членами внешнего класса, вы можете использовать точку (.) для доступа к вложенным классам и их членам.

  • Использование вложенных классов сделает ваш код более читаемым и обеспечит лучшую обертку.

  • Нестатические вложенные классы (внутренние классы) могут доступа к другим членам внешнего/закрытого класса, даже если они объявлены как частные.