Какие существуют особенности использования вложенных классов: статических и внутренних, в чем заключается разница между ними?

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

  1. **Внутренние (non-static inner classes)
    **
  2. **Статические (static nested classes)
    **

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

🔷 1. Что такое вложенные классы?

Вложенные классы — это классы, определённые внутри других классов.

class Outer {
class Inner { } // внутренний класс
static class StaticInner { } // статический вложенный класс
}

🔹 Классификация:

Тип вложенного класса Ключевое слово Особенность
Внутренний класс (inner) Без static Имеет ссылку на внешний объект
--- --- ---
Статический вложенный класс С static Не имеет ссылки на внешний объект
--- --- ---
Локальный класс Внутри метода Ограничена областью видимости метода
--- --- ---
Анонимный класс Без имени Используется для создания одноразовых объектов
--- --- ---

В этом ответе мы фокусируемся на первых двух: inner и static nested.

🧠 Внутренние классы (Inner Class)

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

▶ Пример:

class Outer {
private String message = "Hello from Outer";
class Inner {
void printMessage() {
System.out.println(message); // доступ к private-полю внешнего класса
}
}
}

▶ Использование:

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.printMessage(); // Hello from Outer

📌 Особенности inner class:

Особенность Детали
Имеет ссылку на объект внешнего класса Да
--- ---
Может обращаться к полям и методам ✅ Даже к private
--- ---
Нельзя объявить static поля/методы ❌ Только нестатические
--- ---
Создаётся через объект внешнего класса Outer.Inner inner = outer.new Inner()
--- ---

🔷 Статические вложенные классы (Static Nested Class)

Этот класс определён внутри другого, но не имеет доступа к нестатическим членам внешнего класса.
Он работает как обычный статический класс — просто вложен внутрь другого для логической структуры.

▶ Пример:

class Outer {
private static String staticMessage = "Static Hello";
static class StaticInner {
void printStaticMessage() {
System.out.println(staticMessage);
}
}
}

▶ Использование:

Outer.StaticInner inner = new Outer.StaticInner();
inner.printStaticMessage(); // Static Hello

📌 Особенности static nested class:

Особенность Детали
Имеет ссылку на объект внешнего класса ❌ Нет
--- ---
Доступ к нестатическим полям внешнего ❌ Нельзя
--- ---
Доступ к статическим полям внешнего ✅ Можно
--- ---
Может содержать статические члены ✅ Да
--- ---
Создаётся без экземпляра внешнего Outer.StaticInner inner = new Outer.StaticInner();
--- ---

🔁 Сравнение inner vs static nested

Критерий Внутренний (inner) Статический (static nested)
Ссылка на внешний объект ✅ Есть ❌ Нет
--- --- ---
Доступ к private внешнего ✅ Да ✅ Только к static
--- --- ---
Создаётся через внешний объект ✅ Да ❌ Нет
--- --- ---
Может содержать static поля ❌ Нет ✅ Да
--- --- ---
Применение Класс, логически зависим от объекта внешнего класса Вспомогательный, утилитный класс
--- --- ---

🛠 Когда использовать?

Сценарий Тип класса
Класс нужен только внутри одного объекта Внутренний (inner)
--- ---
Класс не зависит от конкретного объекта внешнего класса Статический
--- ---
Нужно вложить класс для логической группировки Оба подойдут
--- ---
Класс должен использовать только static члены внешнего Статический
--- ---

🧩 Резюме:

Тип Особенности
Inner Class - Создаётся через объект внешнего класса- Имеет доступ к его нестатическим членам
--- ---
Static Nested Class - Не зависит от экземпляра внешнего класса- Может содержать static поля и методы
--- ---

✅ Пример сравнения:

class Outer {
private int value = 100;
private static int staticValue = 200;
class Inner {
void show() {
System.out.println(value); //  доступ к нестатическим
}
}
static class StaticInner {
void show() {
// System.out.println(value);  ошибка
System.out.println(staticValue); // 
}
}
}