JavaRush /Курси /Java Syntax Zero /Статичні методи

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

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

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

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

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


Коментарі (10)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
RMykola Рівень 20
25 лютого 2025
В останній задачі попався на те, що змінив тип тільки змінної, а на тип методів, які посилались на ці змінні, не звернув уваги.
Андрій Рівень 18
4 січня 2024
Останнім часом приходиться переглядати купа статей та відео, щоб зрозуміти тему(і те не завжди допомагає).
Mykola Рівень 15 Expert
23 серпня 2023
Пролайкайте комент, будь ласка
Kostiantyn Bogatyrchuk Рівень 14 Expert
24 лютого 2023
голова квадратна. хз як це запам'ятати😒
Svitoij Рівень 23
30 березня 2023
На словах взагалі не зрозуміло, а в задачці дойшло))
Павло Левко Рівень 1
15 лютого 2023
В задачі конвертертрядка, можна оголосити змінну прямо перед перетворенням методу. Так код виглядає зрозумілішим і простішим. double temp = Double.parseDouble(string); System.out.println((Math.round(temp))); Всього два рядки :)
Іван Рівень 73 Expert
25 квітня 2023
Якщо не помиляюсь в консоль має видати відповідь - 13.0, задачка не мала б пройти валідацію, бо в умові написано 13. Треба перетворити дабл на інт.
Julia Oskilko Рівень 34
3 жовтня 2023
все правильно, при використанні Math.round то воно приведе до типу int Math.round: This method returns the value of the argument rounded to the nearest int value.
Roma Chernesh Рівень 16
17 січня 2023
Дуже гарна стаття, багато що мені прояснила! Ще доповню відповідь на питатння "Навіщо потрібні статичні методи, якщо вони настільки обмежені?" Не споречаюся, що вони потрібні "коли, не треба передавати ніяких посилань на об'єкт". Це вірно! Але ж не пояснює "навіщо". Та навіть не зрозуміло, де їх треба використовувати (приклад був із методом main, але ж не заради одного методу вигадали слово static) *ІМХО Це як на питання "навіщо потрібен залізничний потяг?" відповісти "ми використовуємо потяг, коли ми купити квиток на потяг". А МАЄ БУТИ (на питання "навіщо") "ми використовуємо потяг, бо ми хочемо кудись, щось/когось відвести, використовуючи рельси/шпали". Сподіваюся мій приклад не звучить занадто надуманим)) Короче, гугління питання "навіщо взагалі цей static в Java" Дало ось яку відподь: Зазвичай статичні методи використовуються для реалізації функцій, які належать до класу, але не мають бути пов'язані із окремим об’єктом цього класу.. Прикладом може бути так званий “фабричний” метод. (Раджу за це почитати, тим хто вперше чує. А ті хто і так знають, думаю, зрозуміють цей приклад). Статичні методи також використовуються в класах, що пов’язані з базою даних. Коли потрібно зробити пошук/збереження/видалення записів із бази даних. Тобто відповідь на питання "Навіщо потрібні статичні методи" >> - Статичні методи потрібні, для обробки даних класу, незалежно від будь-якого об'єкту цього класу. Прикладом цьому є пошук/збереження/видалення записів із бази даних. Повторюся, що стаття все одно гарна. Просто хотів допомогти комусь у майбутньому, хто як і я не все сходу зрозумів.
Neridnyi Taras Рівень 23
12 жовтня 2022
Зараз неважко)