Вложенные классы и внутренние классы. Статические вложенные классы. Примеры

Вложенные классы и внутренние классы. Статические вложенные классы. Примеры


Содержание


1. Какие классы называются вложенными классами? Особенности использования вложенных классов

Вложенный класс – это класс, который объявлен в другом классе. При объявлении вложенного класса в пределах другого (внутри блока фигурных скобок { }) этот вложенный класс воспринимается как член охватывающего его класса.

Вложенный класс имеет доступ ко всем членам данных и методам охватывающего класса (даже к private-членам данных), так как он получает ссылку на внешний объект (объект охватывающего класса), который его создал.

Класс может содержать любое количество вложенных классов.

Например

class OutClass {
    // члены данных и методы охватывающего (внешнего) класса
    // ...

    class InClass {
        // члены данных и методы вложенного (внутреннего) класса
        // ...
    }
}

В вышеприведенном примере объявляется вложенный класс с именем InClass в пределах области действия охватывающего класса с именем OutClass.

 

2. Может ли вложенный класс существовать независимо от охватывающего (внешнего) класса?

Вложенный класс не может существовать независимо от охватывающего класса. Однако, объект вложенного класса можно создавать.

 



3. Какие существуют типы вложенных классов с точки зрения доступа к классу?

Существует два типа вложенных классов:

  • статические вложенные классы. Такие классы объявляются с модификатором доступа static;
  • нестатические вложенные классы или внутренние классы. Это классы, объявленные в пределах фигурных скобок внешнего (охватывающего) класса.

 

4. Что означают термины «внутренний класс» и «вложенный класс»?

Внутренний класс – это обычный нестатический вложенный класс. То есть, это класс, который объявлен в пределах другого класса без ключевого слова static. Если класс объявлен с ключевым словом static (статический вложенный класс), то такой класс еще называют вложенным классом.

 

5. Особенности объявления и использования статического вложенного класса в нестатическом классе. Пример

Если вложенный класс объявлен с ключевым словом static, то в этом случае можно выделить следующие основные моменты:

  • любой public-статический класс имеет глобальную область видимости, то есть, он есть видимым из всех классов. А потому, можно обращаться к имени этого класса с учетом иерархии вложения. Например, если статический класс с именем B есть вложенным в класс с именем A, то обращение к этому классу будет A.B;
  • из статического вложенного класса нельзя непосредственно иметь доступ к нестатическим членам данных и методам охватывающего (внешнего) класса. Однако, можно доступиться к статическим членам данных охватывающего класса;
  • из охватывающего класса нельзя иметь доступ к нестатическим public-членам данных и методам статического внутреннего класса непосредственно. Для обеспечения доступа должен быть создан объект статического вложенного класса.

Пример.

Объявляется класс OutData, в котором объявлен вложенный статический класс InData.

// охватывающий класс
class OutClass {
    int d;
    int x;

    // конструктор
    OutClass() {
        d = 15;
        x = 20;
    }

    // внутренний метод класса OutClass
    void DemoOut() {
        // можно объявлять объект вложенного статического класса
        InClass ic = new InClass();

        // доступ к внутренним данным статического класса InClass через объект класса
        ic.a = 25;
        ic.d = 33;

        // можно объявлять объект охватывающего класса
        OutClass oc = new OutClass();
        oc.d = 78;
        oc.x = 323;
    }

    // вложенный статический класс
    static class InClass {
        int a;
        int d;

        // конструктор
        InClass() {
            // доступ к переменным a, d этого класса
            a = 5;
            d = 10;

            // нельзя доступиться к переменным d,x класса OutClass,
            // поскольку из статического класса к нестатическому члену данных нет доступа
            //x = 30; - ошибка
        }

        // внутренний метод в статическом классе
        void DemoIn() {
            // можно создавать объект класса OutClass
            OutClass oc = new OutClass();
            oc.d = 55;
            oc.x = 77;

            // можно создавать объект статического класса InClass
            InClass ic = new InClass();
            ic.a = 33;
            ic.d = 55;
        }
    }

    void DemoMethod() {
        // доступ к статическому классу из нестатического метода
        OutClass.InClass IC = new OutClass.InClass();
        int t;
        t = IC.a;
        System.out.println("t = " + t);
    }
}

Ниже демонстрируется использование классов OutClass и InClass

// можно объявлять объекты как охватывающего так и внутреннего классов
OutClass.InClass i = new OutClass.InClass(); // создать экземпляр из статического класса
OutClass o = new OutClass(); // создать экземпляр охватывающего нестатического класса
int t;

t = iC.a; // t = 5
t = o.d; // t = 15

// демонстрация вызова методов классов OutClass и OutClass.InClass
iC.DemoIn();
oC.DemoOut();

 

6. Особенности использования вложенных классов в случае, когда оба класса объявлены как нестатические. Пример

Охватывающий и вложенный классы могут быть объявлены без ключевого слова static. В этом случае работа с классами имеет следующие особенности:

  • если в некотором классе объявляется вложенный нестатический класс, то этот класс еще называют «внутренним» классом;
  • из вложенного (внутреннего) класса есть доступ ко всем членам данных и методам охватывающего класса;
  • чтобы использовать вложенный класс, в методе охватывающего класса должен быть создан экземпляр (объект) вложенного класса.

Пример.

class OutClass {
    int d;
    int x;

    // конструктор
    OutClass() {
        d = 15;
        x = 20;
    }

    // внутренний метод класса OutClass
    void DemoOut() {
        // можно объявлять объект вложенного класса из охватывающего класса
        InClass ic = new InClass();
        ic.a = 25;
        ic.d = 33;

        // можно объявлять объект охватывающего класса
        OutClass oc = new OutClass();
        oc.d = 78;
        oc.x = 323;

        // из охватывающего класса нельзя непосредственно доступиться к данным и методам вложенного класса,
        // поскольку не создан экземпляр вложенного класса
        // InClass.this.a = 22; - ошибка!
    }

    // вложенный нестатический класс
    class InClass {
        int a;
        int d;

        // конструктор
        InClass() {
            // доступ к переменным a, d вложенного класса InClass
            a = 5; // OutClass.InClass.this.a = 5
            OutClass.InClass.this.d = 10; // d = 10;

            // можно доступиться к переменным d,x класса OutClass,
            x = 30;
            OutClass.this.d = 35;
        }

        // внутренний метод
        void DemoIn() {
            // можно создавать объект класса OutClass
            OutClass oc = new OutClass();
            oc.d = 55;
            oc.x = 77;

            // можно создавать объект класса InClass
            InClass ic = new InClass();
            ic.a = 33;
            ic.d = 55;
        }
    }
}

 

7. Особенности использования вложенных классов в случае, когда оба класса объявлены как статические

Статические классы имеют глобальную область видимости из всех других классов и методов (статических и нестатических) если они объявлены как public.

Особенности использования вложенных статических классов:

  • можно объявлять экземпляры вложенных public-статических классов;
  • на уровне доступа пакета запрещено объявлять статический класс (см. рисунок 1-1);
  • статический класс можно объявлять как вложенный класс в другом нестатическом классе как было продемонстрировано в п. 7 данной темы (рисунок 1-2).

Java Eclipse объявление статического вложенного класса

Рис. 1. Объявление статического вложенного класса: 1 — ошибка, запрещено объявлять в пределах пакета; 2 — разрешено объявлять в пределах класса

Статический вложенный класс может быть объявлен в статическом охватывающем классе. Однако, этот статический охватывающий класс может быть реализован внутри нестатического охватывающего класса. В этом случае получается два уровня вложения.

Ниже приведен упрощенный пример объявления статического вложенного класса в статическом охватывающем классе.

// охватывающий нестатический класс
class OutClass {
    int d;

    // вложенный статический класс
    static class InClass {
        int d;

        // вложенный статический класс в статическом охватывающем классе InClass
        static class InClass2 {
            int d2;
        }
    }
}

Как видно из вышеприведенного кода, объявляется класс OutClass, который есть охватывающим (внешним) по отношению к статическому классу InClass. В свою очередь, статический класс InClass есть охватывающим по отношению к статическому классу InClass2.

Использование объекта класса InClass2 может быть следующим

// объявить объект класса OutClass.InClass.InClass2
OutClass.InClass.InClass2 obj = new OutClass.InClass.InClass2();
int t;
obj.d2 = 23; // OutClass.InClass.InClass2.d
t = obj.d2;

 

8. Особенности объявления и использования нестатического вложенного класса в статическом охватывающем классе

В статическом охватывающем классе объявить нестатический вложенный класс можно. Однако, при попытке создать экземпляр такого нестатического класса компилятор Java выдаст ошибку

No enclosing instance of type OutClass.InClass is accessible. Must qualify the allocation with an enclosing instance of type OutClass.InClass (e.g. x.new A() where x is an instance of OutClass.InClass).

Итак, использовать нестатические вложенные классы в статических охвытывающих классах запрещено.

 


Связанные темы