1. Статичні методи

Окрім статичних змінних, у класах можуть також бути статичні методи.

Звичайні методи прив'язані до об'єктів (екземплярів) класу й можуть звертатися до звичайних змінних класу (а також до статичних змінних і методів). Натомість статичні методи прив'язані до статичного об'єкта класу й можуть звертатися тільки до статичних змінних і/або інших статичних методів класу.

Щоб викликати звичайний метод класу, спочатку потрібно створити об'єкт цього класу, а тільки потім можна викликати метод для створеного об'єкта. Викликати звичайний метод не в об'єкті, а в класі не можна.

Приклад:

Викликати нестатичний метод у класі не можна!
public class DataInfo
{
   public int getValue()
   {
      return 100;
   }
}

public class Solution
{
   public static void main(String[] args)
   {
      System.out.println(DataInfo.getValue()); // Тут буде помилка!
   }
}

А для виклику статичного методу досить наявності статичного об'єкта класу (який завжди існує після завантаження класу в пам'ять). Саме тому метод main () — статичний. Він прив'язаний до статичного об'єкта класу, і для його виклику не потрібно створювати ніяких об'єктів.

Щоб оголосити метод статичним, потрібно перед заголовком методу написати ключове слово static. Загальний вигляд цієї конструкції такий:

static тип ім'я(параметри)
{
   код методу
}

Приклади:

Код Примітка
public class Solution
{
   public static void main(String args[])
   {
      test();
   }

   public static void test()
   {
      int d = 2/0;
   }
}


Метод main викликається Java-машиною за допомогою команди Solution.main();



Виклик статичного методу test() здійснюється у статичному методі main().

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

Тип ім'я = Ім'яКласу.ім'яМетоду(параметри)

Приклади:

Код Статичний метод
int x = Math.min(a, b);
int min(int a, int b)
Thread.sleep(200);
void sleep(long ms)
Path path = Path.of("c:\\readme.txt");
Path of(String str)


2. Статичні та звичайні методи

У чому ж відмінність статичних методів від звичайних?

Звичайний метод має прив'язку до об'єкта — екземпляра класу, а статичний метод такої прив'язки не має. Звичайний метод може звертатися до змінних у своєму екземплярі класу, а статичний — ні: у нього просто немає жодного екземпляра класу, пов'язаного з ним.

Відмінності між цими двома типами методів показано в таблиці:

Характеристика Звичайний метод Статичний метод
Є зв'язок з екземпляром класу Так Ні
Може викликати звичайні методи класу Так Ні
Може викликати статичні методи класу Так Так
Може звертатися до звичайних змінних класу Так Ні
Може звертатися до статичних змінних класу Так Так
Можна викликати для об'єкта Так Так
Можна викликати для класу Ні Так

Навіщо потрібні такі методи, якщо вони настільки обмежені? Річ у тім, що такий підхід теж має свої переваги.

По-перше, щоб звернутися до статичних методів і змінних, не треба передавати ніяких посилань на об'єкт.

По-друге, часом є потреба мати тільки один екземпляр змінної, наприклад, такої змінної як System.out (статична змінна out класу System).

І, по-третє, іноді потрібно викликати метод раніше, ніж з'явиться можливість створювати якісь об'єкти. Це, наприклад, виклик методу main (), з якого починається виконання програми: Java-машина викликає його ще до створення екземпляра класу.

Є зв'язок з екземпляром класу

Під час виклику звичайного методу в нього передається прихований параметр — об'єкт, для якого його викликано. Цей параметр має ім'я this. Саме цей прихований параметр — посилання на об'єкт, для якого викликано метод, — і відрізняє звичайні методи від статичних.

У статичних методів такого прихованого параметра немає, тому всередині статичних методів не можна користуватися ключовим словом this. Крім того, зі статичного методу не можна викликати нестатичний: посилання на екземпляр класу просто немає звідки взяти.

Може викликати звичайні методи класу

У звичайному методі класу завжди є прихований параметр — this, тобто посилання на об'єкт класу, чий метод було викликано. Щоразу, коли ви викликаєте звичайний метод всередині іншого звичайного методу, для цього виклику використовується прихований параметр this. Приклад

Код Як це працює
int min(int a, int b)
{
   return a < b ? a : b;
}

int min(int a, int b, int c)
{
   int t = min(a, b);
   return min(t, c);
}
int min(int a, int b)
{
   return a < b ? a : b;
}

int min(int a, int b, int c)
{
   int t = this.min(a, b);
   return this.min(t, c);
}

Саме тому неможливо викликати звичайний метод зі статичного. Усередині статичного методу просто немає прихованої змінної з ім'ям this.

Можна уявити іншу ситуацію: у програмі ще не створено жодного об'єкта нашого класу. Чи можна викликати статичний метод класу? Так. А чи зможе цей статичний метод викликати звичайний метод?

І для якого об'єкта він його викличе? Адже немає ще жодного екземпляра нашого класу!

Може викликати статичні методи класу

Статичні методи можна викликати звідки завгодно — з будь-якого місця програми. Тобто їх можна викликати як зі статичних методів, так і зі звичайних. Жодних обмежень тут немає.

Може звертатися до звичайних змінних класу

Зі звичайного методу можна звертатися до звичайних змінних класу, тому що в цьому разі відбудеться звернення до змінних екземпляра класу, який легко отримати з прихованого параметра this.

Статичний метод не знає, з якого саме екземпляра класу йому потрібно брати значення звичайних змінних. Може легко статися така ситуація, коли статичний метод викликано, а в програмі ще не створено жодного екземпляра класу.

Тому статичні методи не можуть звертатися до звичайних змінних класу.

Статичний метод викликає звичайний метод, от тільки для якого об'єкта його слід викликати?

Невідомо! От тому й не можна викликати звичайний метод зі статичного, не вказуючи посилання на об'єкт!

Може звертатися до статичних змінних класу

Ситуація зі зверненням до статичних змінних така сама, як і зі зверненнями до статичних методів. До статичних змінних можна звертатися з будь-якого місця в програмі. А це означає, що можна звертатися зі статичних і звичайних методів.

Можна викликати для об'єкта

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

Код Як його бачить компілятор
Thread th = Thread.current();
th.sleep(1000);
Thread th = Thread.current();
Thread.sleep(1000);
Integer i = 1;
int x = i.parseInt("12");
Integer i = 1;
int x = Integer.parseInt("12");
"".valueOf(12);
String.valueOf(12);

Можна викликати для класу

Для класу можна викликати тільки статичний метод, а для виклику звичайного методу потрібне посилання на екземпляр класу. Тому не можна викликати звичайний метод за допомогою конструкції формату Ім'яКласу.ім'я методу(параметри)