Статичні поля та методи
Статичні поля
Поле, що має модифікатор static, існує в одному екземплярі. Якщо поле не статичне, кожен об'єкт містить його копію. Наприклад, потрібно надати унікальний ідентифікатор кожному співробітнику. Додамо в клас Employee поле id та статичне поле nextId:
Тепер кожен об'єкт Employee має своє поле id, крім того є поле nextId, яке одночасно належить всім екземплярам класу.
Наприклад, якщо існує тисяча об'єктів Employee, то вони мають тисячу полів id, по одному в кожному об'єкті. При цьому існує лише один екземпляр статичного поля nextId. Навіть якщо не створено жодного об'єкта Employee, статичне поле nextId існує. Воно належить класу, а чи не конкретному об'єкту.
У більшості об'єктно-орієнтованих мов статичні поля називаються полями класу -class field. Термін "статичний" успадкований від мови C++.
Додамо до класу Employee наступний метод:
Допустимо, потрібно задати ідентифікаційний номер об'єкту harry:
Тепер значення поля id об'єкта harry встановлено, а значення статичного поля nextId збільшено на одиницю.
На відміну від статичних змінних, статичні константи використовуються набагато частіше. Наприклад, клас Math має статичну константу PI:
Звернення до статичної константи:
Без ключового слова static, константа PI була б звичайним полем екземпляра класу Math. Тобто для виклику PI довелося б створювати об'єкт Math, причому кожен подібний об'єкт мав би свою копію константи PI.
Ще одна статична змінна, що часто використовується - System.out з класу System:
Застосовувати загальнодоступні поля ніколи не слід, оскільки будь-який об'єкт зможе змінити їх значення. Але, відкриті константи (поля,оголошені як final) можна використовувати сміливо. Поле out оголошено як final, і йому не можна присвоїти інший потік висновку:
У класі System є метод setOut(), що дозволяє присвоїти полю System.out інший потік. Метод setOut -платформно-орієнтований, він реалізований засобами, відмінними від Java. Платформенно-орієнтовані методи можуть оминати механізми контролю Java. Це дуже специфічне рішення, яке не слід повторювати у своїх програмах.
Статичні методи
Статичні методи виконуватимуться, навіть якщо екземпляр класу не існує. Наприклад, метод pow() з класу Math – статичний. Вираз Math.pow(x, y) обчислює x^y. При виконанні свого завдання цей метод не використовує жодного екземпляра класу Math. Тобто. він немає неявного параметра. У статичних методах цей об'єкт не використовується.
Статичні методи не працюють із об'єктами; з їх допомогою неможливо отримати доступ до полів екземпляра. Однак, статичні методи мають доступ до статичних полів класу.
Для виклику методу необхідно вказати ім'я класу:
Якщо з опису методу видалити ключове слово static, для виклику методу потрібно створити об'єкт типу Employee.
Для виклику статичного методу можна використовувати об'єкти. Наприклад, замість Employee.getNextId() можна вказати harry.getNextId(), за умови, що harry - це екземпляр класу Employee. Але для обчислення результату метод getNextId() не звертається до об'єкта harry, і подібне вираження ускладнює сприйняття програми. Рекомендується для виклику статичних методів використовувати імена класів, а чи не об'єкти.
Статичні методи слід застосовувати у двох випадках:
- Коли методу не потрібний доступ до інформації про стан об'єкта, оскільки всі необхідні параметризадаються явно: Math.pow (3, 4);
- Коли методу необхідний доступ лише до статичним полям класу: Employee.getNextId().
Статичні поля та методи Java та C++ відрізняються тільки синтаксично. C++ для доступу до статичного поля або методу, що знаходиться поза область видимості, використовується вираз: Math::PI.
Термін "static" - історичний курйоз. Спочатку ключове слово static було введено в мові C для позначення локальних змінних, які не знищувалися при виході блоку. У цьому контексті static має сенс: змінна продовжує існувати після виходу з блоку, а також повторного входу в нього. Потім static в C придбало друге значення - глобальні змінні та функції, до яких не можна отримати доступ з інших файлів. У результаті, у C++ це слово означає змінні та функції, що належать класу, але не належать жодному об'єкту цього класу. Саме це значення має static у Java.
Методи, що породжують
Клас NumberFormat використовує методи, що породжують, для створення об'єктів, що відповідають різним стилям форматування:
Чому ж не використовувати для цього конструктор? Тому є дві причини:
- Конструктору не можна надати довільне ім'я. Його ім'я завжди має співпадати з ім'ям класу. У прикладі з класом NumberFormat можна використовувати різні імена для різних типів форматування.
- При використанні конструктора тип об'єкта фіксований. Якщо ж застосовуються методи, що породжують, вони повертають об'єкт DecimalFormat, який успадковує властивості NumberFormat.
Метод main()
Статичні методи можна викликати, навіть якщо відповідний об'єкт ще створено. Наприклад, для виклику методу Math.pow() об'єкт Math не потрібний. Тому метод main()оголошується як статичний:
Кожен клас може містити метод main(). Його можна використати для незалежного тестування класів. Наприклад, метод main() можна додати до класу Employee:
Для тестування класу Employee слід виконати команду:
Додаток, частиною якого є клас Employee, запускається так:
У цьому випадку метод main() класу Employee не буде виконаний.
Наступна версія класу Employee містить статичне поле nextId та статичний метод getNextId(). Масив заповнюється трьома об'єктами Employee, а потім виводиться інформація про співробітників. На закінчення виводиться черговий доступний ідентифікатор:
Клас Employee має статичний метод main() для модульного тестування: