JavaRush /Курси /Java Syntax Zero /Статичні класи

Статичні класи

Java Syntax Zero
Рівень 12 , Лекція 4
Відкрита

1. Внутрішні класи

Нещодавно ви дізналися, що є статичні змінні й статичні методи, однак, виявляється, є ще й статичні класи. Але почнемо здаля.

У мові Java можна оголошувати класи всередині класів. І навіть класи всередині класів, які є всередині класів усередині класів. Вигляд такого оголошення дуже простий:

class ЗовнішнійКлас
{
   змінні класу
   методи класу 
   class ВнутрішнійКлас
   {
      змінні класу
      методи класу
   }
}

Просто оголошуємо один клас усередині іншого — і готово.

Приклад:

public class Solution
{
   static ArrayList<Point> points = new ArrayList<Point>();

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points.add(point);
   }

   static class Point
   {
      int x;
      int y;
   }
}

Внутрішні класи можуть бути статичними й нестатичними. Статичні класи ще називають вкладеними (static nested class), нестатичні називають просто внутрішніми класами (inner class).



2. Статичні класи

Статичні вкладені класи можна використовувати поза батьківським класом. Клас, який має модифікатор доступу public, можна використовувати в будь-якому місці програми. Такі класи майже нічим не відрізняються від будь-якого звичайного класу. Проте є кілька відмінностей.

Ім'я класу

Якщо потрібно звернутися до статичного вкладеного класу не з його батьківського класу, а з іншого місця в програмі, слід вказати ім'я класу: воно складається з імені батьківського класу та імені вкладеного класу. Загальний вигляд цього імені такий:

БатьківськийКлас.ВкладенийКлас

Приклади:

Батьківський клас Вкладений клас Повне ім'я вкладеного класу
com.javarush.Solution
Point
com.javarush.Solution.Point
java.util.Map
Entry
java.util.Map.Entry
java.util.Files
DirectoryStream
java.util.Files.DirectoryStream
java.nio.WindowsPath
Closeable
java.nio.WindowsPath.Closeable

Якщо вкладений клас має свій вкладений клас, їхні імена просто склеюють через крапку.

Типовий приклад вкладеного класу в JDK — це клас Entry всередині класу Map. Якщо ви хочете отримати множину пар елементів з об'єкта HashMap, то метод entrySet() поверне вам множину пар типу Set<Map.Entry>.

Власне, запис Map.Entry — це і є зовнішній і внутрішній класи.

Створення об'єкта

Створити об'єкт вкладеного статичного класу дуже легко. Дивіться як:

БатьківськийКлас.ВкладенийКлас ім'я = new БатьківськийКлас.ВкладенийКлас();

Усе так само, як зі звичайними класами, тільки ім'я подвійне.

Звернення до статичних методів

Якщо статичний клас має статичні методи, до них можна звертатися так само, як до статичних методів звичайних класів (тільки ім'я класу тепер подвійне).

БатьківськийКлас.ВкладенийКлас.статичнийМетод();

Звернення до статичних змінних

Звертатися до публічних статичних змінних вкладеного класу теж просто:

БатьківськийКлас.ВкладенийКлас.ім'яСтатичноїЗмінної;


3. Особливості статичних класів

Статичні внутрішні класи, по суті, не варто називати статичними. Вони поводяться так само, як і звичайні класи. Ніяких обмежень на звернення до них із нестатичних методів немає.

Якщо ви працюєте з внутрішнім статичним класом усередині його батьківського класу, то взагалі не помітите жодної різниці між цим внутрішнім класом і звичайним класом (не вкладеним і не статичним).

Приклад:

Внутрішній статичний клас Point Звичайний клас Point
public class Solution
{
   static ArrayList<Point> points;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points = new ArrayList<Point>();
      points.add(point);
   }

   static class Point
   {
      int x;
      int y;
   }
}
public class Solution
{
   static ArrayList<Point> points;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;
      points = new ArrayList<Point>();
      points.add(point);
   }
}

class Point
{
   int x;
   int y;
}

Якщо якийсь вкладений статичний клас перенести з батьківського класу назовні, нічого не зміниться, крім того, що новий клас утратить здатність звертатися до приватних статичних (private static) змінних і методів колишнього батьківського класу.

Приклад:

Внутрішній статичний клас Point Звичайний клас Point
public class Solution
{    private static ArrayList<Point> points;

   static class Point
   {
      int x;
      int y;

      public static void main(String[] args)
      {
         Point point = new Point();
         point.x = 100;
         point.y = 200;

         // працюватиме
         points = new ArrayList<Point>();
         points.add(point);
      }
   }
}
public class Solution
{
   private static ArrayList<Point> points;
}

class Point
{
   int x;
   int y;

   public static void main(String[] args)
   {
      Point point = new Point();
      point.x = 100;
      point.y = 200;

      // тут буде помилка
      points = new ArrayList<Point>();
      points.add(point);
   }
}

Метод main у звичайному класі Point не може звертатися до приватної статичної (private static) змінної points класу Solution!

Це, власне, і є основною відмінністю вкладеного статичного класу від звичайного класу. Методи вкладеного статичного класу мають доступ до всіх статичних змінних і методів свого батьківського класу, навіть якщо їх оголошено як private.

Ну а якщо подумати, то що тут дивного? Модифікатор private прямо вказує, що до змінних і методів, позначених цим модифікатором, можна звертатися тільки зсередини їхнього класу. Внутрішній статичний клас міститься всередині батьківського класу? Якщо так, тоді ніяких проблем: звертайтеся скільки завгодно.


Коментарі (16)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Сергій Рівень 44 Expert
17 березня 2023
трохи бiльше про внутрiшнi класи: https://javarush.com/groups/posts/2181-vlozhennihe-vnutrennie-klassih
IronMan57 Рівень 28
15 грудня 2024
Дякую за посилання. Також до цієї теми відноситься ще одна стаття - Статические вложенные классы
Roma Chernesh Рівень 16
18 січня 2023
Для тих, хто хоче зрозуміти третю задачу: Outer.Inner inner = new Outer().new Inner(); //цей код викликає об'єкт зовнішнього класу "new Outer()" а об'єкт зовнішнього класу "new Outer()" в свою чергу викликає об'єкт внутрішнього класу "new Inner()" Outer.Nested nested = new Outer.Nested(); //цей код викликаэ об'єкт зовнішнього класу. І все. Чому така різниця? Сенс у тому, що для створення Nested (вкладенного) класу не потрібен об'єкт зовнішнього класу "new Outer()". А Inner (внутрішній) клас потребує об'єкт зовнішнього класу. Чому вкладенний не потребує, а внутрішній - потребує? Так один з них статік! А статичні члени пов'язані напряму із класом, а не із об'єктом. Кому це "пояснення" нічого не пояснило, то раджку просто запам'ятати "static - нема об'єкту" "нема слова статік - об'єкт має бути"
Svitoij Рівень 23
30 березня 2023
Взагалі срака якась, добре, що побачив твій комент, зекономив час :)
Костянтин Рівень 58 Expert
1 червня 2023
Дякую, бо теж не одразу зрозумів як створюються об'єкти внутрішніх класів за межами зовнішніх класів, а в лекції про це якось не дуже сказано
Olexandr Рівень 47
3 січня 2024
Для зовсім зовсім новачків, таких як я, які не відразу в'їхали що означає Outer.Inner inner = new Outer().new Inner(); Це можна замінити двома рядками простіше для розуміння: Outer xxx = new Outer(); // створюємо об'єкт зовнішнього класу Outer.Inner www = xxx.new Inner (); // створюємо об'єкт внутрішнього класу на основі об'єкту зовнішнього, який ми створили перед цим.
Кирило Рівень 43
9 липня 2024
Базовано пояснив
Yaroslav Tkachyk Рівень 23 Expert
1 січня 2023
Ще дві статті, які краще допоможуть розкрити дану тему: Статичні вкладені класи Класи, види вкладених класів з прикладами
Niko Рівень 36
21 липня 2022
Це допоможе. https://javarush.com/groups/posts/2181-vlozhennihe-vnutrennie-klassih
Yaroslav Tkachyk Рівень 23 Expert
1 січня 2023
Досить цікавий момент в даній статті: Класи, які створюються всередині батьківського класу називаються вкладеними (nested classes). Їх є два види: 1. Статичні вкладені класи (static nested classes) 2. Нестатичні вкладені класи (non-static nested classes) == (inner classes) внутрішні класи. В даній лекції трішки навпаки. Потрібно виправити...
User Undefined Рівень 32
22 січня 2022
Добре було б в лекції таку конструкцію описати

OuterClass outerObject = new OuterClass();
InnerClass innerObject = outerObject.new InnerClass();
bodyabtc Рівень 16
1 серпня 2022
Згоден, в кінцевій задачі, сам гуглив щоб дізнатись як створити звичайний внутрішній клас.
7 листопада 2022
в тому і прикол)
Taras Woytowitch Рівень 16
9 січня 2023
Так буде правильніше і легше для розуміння)

Outer.Inner inner = new Outer().new Inner();
Roma Chernesh Рівень 16
18 січня 2023
задача тоді мала бути Hard, бо ми цю тему не проходили.
StepanPantera Рівень 27
2 грудня 2021
БатьківськийКлас.ВкладенийКлас.ім'яСтатичноїЗмінної(); - це помилка Треба писати в кінці без дужок