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

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

Відкрита

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).


12
Задача
Java Syntax Zero,  12 рівень,  4 лекція
Недоступна
Двигун — серце автомобіля
Двигун — серце автомобіля

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 БатьківськийКлас.ВкладенийКлас();

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

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

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

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

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

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

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

12
Задача
Java Syntax Zero,  12 рівень,  4 лекція
Недоступна
Утилітний калькулятор
Утилітний калькулятор

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 прямо вказує, що до змінних і методів, позначених цим модифікатором, можна звертатися тільки зсередини їхнього класу. Внутрішній статичний клас міститься всередині батьківського класу? Якщо так, тоді ніяких проблем: звертайтеся скільки завгодно.


12
Задача
Java Syntax Zero,  12 рівень,  4 лекція
Недоступна
Об'єкти внутрішніх і вкладених класів
Об'єкти внутрішніх і вкладених класів
Коментарі (16)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Сергій
Рівень 44
Expert
17 березня 2023, 18:51
трохи бiльше про внутрiшнi класи: https://javarush.com/groups/posts/2181-vlozhennihe-vnutrennie-klassih
IronMan57
Рівень 28
15 грудня 2024, 23:16
Дякую за посилання. Також до цієї теми відноситься ще одна стаття - Статические вложенные классы
Roma Chernesh
Рівень 16
18 січня 2023, 16:15
Для тих, хто хоче зрозуміти третю задачу: 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, 17:17
Взагалі срака якась, добре, що побачив твій комент, зекономив час :)
Костянтин
Рівень 58
Expert
1 червня 2023, 12:15
Дякую, бо теж не одразу зрозумів як створюються об'єкти внутрішніх класів за межами зовнішніх класів, а в лекції про це якось не дуже сказано
Olexandr
Рівень 16
3 січня 2024, 13:57
Для зовсім зовсім новачків, таких як я, які не відразу в'їхали що означає Outer.Inner inner = new Outer().new Inner(); Це можна замінити двома рядками простіше для розуміння: Outer xxx = new Outer(); // створюємо об'єкт зовнішнього класу Outer.Inner www = xxx.new Inner (); // створюємо об'єкт внутрішнього класу на основі об'єкту зовнішнього, який ми створили перед цим.
Кирило
Рівень 43
9 липня 2024, 08:43
Базовано пояснив
Yaroslav Tkachyk
Рівень 23
Expert
1 січня 2023, 12:09
Ще дві статті, які краще допоможуть розкрити дану тему: Статичні вкладені класи Класи, види вкладених класів з прикладами
Niko Java Developer
21 липня 2022, 14:27
Це допоможе. https://javarush.com/groups/posts/2181-vlozhennihe-vnutrennie-klassih
Yaroslav Tkachyk
Рівень 23
Expert
1 січня 2023, 10:44
Досить цікавий момент в даній статті: Класи, які створюються всередині батьківського класу називаються вкладеними (nested classes). Їх є два види: 1. Статичні вкладені класи (static nested classes) 2. Нестатичні вкладені класи (non-static nested classes) == (inner classes) внутрішні класи. В даній лекції трішки навпаки. Потрібно виправити...
User Undefined
Рівень 32
22 січня 2022, 20:02
Добре було б в лекції таку конструкцію описати
OuterClass outerObject = new OuterClass();
InnerClass innerObject = outerObject.new InnerClass();
bodyabtc
Рівень 16
1 серпня 2022, 07:49
Згоден, в кінцевій задачі, сам гуглив щоб дізнатись як створити звичайний внутрішній клас.
7 листопада 2022, 13:19
в тому і прикол)
Taras Woytowitch
Рівень 16
9 січня 2023, 08:32
Так буде правильніше і легше для розуміння)
Outer.Inner inner = new Outer().new Inner();
Roma Chernesh
Рівень 16
18 січня 2023, 15:11
задача тоді мала бути Hard, бо ми цю тему не проходили.
StepanPantera Student
2 грудня 2021, 09:13
БатьківськийКлас.ВкладенийКлас.ім'яСтатичноїЗмінної(); - це помилка Треба писати в кінці без дужок