Статичні члени та модифікатор static. Java: коли використовувати статичні методи

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

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

    Статичний метод може бути оголошено як віртуальний метод.

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

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

Нижче представлений клас Circle, у якому визначено статичний метод GetPi. Він використовується для отримання статичного елемента класу fPi.

static void GetPi()

static float fPi;

float Circle::fPi = 3.1415;

Ви можете викликати метод GetPi таким чином:

fNumber = Circle::GetPi();

Зауважте, що об'єкт класу Circle не створюється.

Загальні члени об'єктів класу

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

Загальні елементи класу даних слід оголосити з ключовим словом static. Усі загальні елементи класу треба визначити у тексті програми, зарезервувавши їх у оперативної пам'яті:

( public: int xLeftTop, xRightBottom; int yLeftTop, yRightBottom; static char title; void SetTitle(char*); );char Cwindow::title = "заголовок вікна";

Кожен об'єкт класу Cwindow матиме унікальні координати, що визначаються елементами даних xLeftTop, xRightBottom, yLeftTop, yRightBottom та однаковий заголовок, що зберігається елементом даних title.

Загальні елементи даних у сфері дії свого класу. Методи класу можуть звертатися до загальних елементів так само, як до інших даних із класу:

void SetTitle(char * sSource)

( strcpy(title, sSource); )

Щоб отримати доступ до загальних елементів із програми, треба оголосити їх як public. Для звернення до такої змінної перед її ім'ям треба вказати ім'я класу та оператор::.

printf(Cwindow::title);

Дружні функції та дружні класи

Доступ до елементів класу із програми та інших класів обмежений. Ви можете безпосередньо звертатися до елементів класу, визначених або описаних після ключового слова public. Однак, у деяких випадках, потрібно визначити функцію поза класом або іншим класом, методи якого можуть звертатися безпосередньо до всіх елементів класу, включаючи елементи оголошені як private і protect.

Дружні функції

У Сі ++ ви можете визначити для класу так звану дружню функцію, скориставшись ключовим словом friend. У класі міститься лише оголошення дружньої функції. Її визначення розташоване поза класом. Ви можете оголосити дружню функцію будь-якої секції класу -public, private або protect.

Дружня функція не є елементом класу, але може звертатися до всіх елементів, включаючи private і protect. Одна й та сама функція може бути дружньою для двох або більше класів.

У наступному прикладі визначено функцію Clear, дружню для класу point. Дружня функція Clear використовується для зміни значення елементів даних m_xіm_y, оголошених як private:

// Клас point

// Функція Clear оголошується дружньою класу point

friend void point::Clear(point*);

// Інтерфейс класу...

//==========================================================

// Функція Clear

void Clear(point* ptrPoint)

// Звертаємось до елементів класу, оголошених як private

ptrPoint->m_x = 0;

ptrPoint->m_y = 0;

//==========================================================

// Головна функція

point pointTestPoint;

// Викликаємо дружню функцію

Clear(&pointTestPoint);

За допомогою ключового слова friend ви можете оголосити деякі методи одного класу дружніми для іншого класу. Такі методи можуть звертатися до всіх елементів класу, навіть оголошених як private і protect, незважаючи на те, що вони самі входять до іншого класу.

У наступному прикладі ми визначаємо два класи – line та point. У класі point визначаємо метод Set та оголошуємо його у класі line як дружній. Дружній метод Set може звертатися до всіх елементів класу line:

// Попереднє оголошення класу line

//==========================================================

// Клас point

// Метод Set класу point

void Set (line *);

//==========================================================

// Клас line

// Метод Set класу point оголошується дружньою

// класу point

friend void point::Set(line*);

int begin_x, begin_y;

int end_x, end_y;

//==========================================================

// Функція Clear

point::Set(line* ptrLine)

// Звертаємось до елементів класу line, оголошених як

ptrLine->begin_x = 0;

ptrLine->begin_y = 0;

//==========================================================

// Головна функція

point pointTestPoint;

line lineTestPoint;

// Викликаємо дружній метод

pointTestPoint.Set(&lineTestPoint);

Останнє оновлення: 19.04.2018

Крім звичайних методів та полів клас може мати статичні поля, методи, константи та ініціалізатори. Наприклад, головний клас програми має метод main, який є статичним:

Public static void main(String args) ( )

Для оголошення статичних змінних, констант, методів та ініціалізаторів перед оголошенням вказується ключове слово static .

Статичні поля

Під час створення об'єктів класу кожному за об'єкта створюється своя копія нестатичних звичайних полів. А статичні поля є спільними для класу. Тому вони можуть використовуватися без створення об'єктів класу.

Наприклад, створимо статичну змінну:

Public class Program( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println(Person.counter); // 3 // змінюємо Person.counter Person.counter = 8; Person sam = new Person(); ( private int id; static int counter=1; Person()( id = counter++; ) public void displayId()( System.out.printf("Id: %d \n", id); ) )

Клас Person містить статичну змінну counter, яка збільшується у конструкторі та її значення присвоюється змінній id. Тобто при створенні кожного нового об'єкта Person ця змінна збільшуватиметься, тому у кожного нового об'єкта Person значення поля id буде на 1 більше ніж у попереднього.

Так як змінна counter статична, то ми можемо звернутися до неї в програмі на ім'я класу:

System.out.println(Person.counter); // Отримуємо значення Person.counter = 8; // Змінюємо значення

Консольний висновок програми:

Id = 1 Id = 2 3 Id = 8

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

Також статичними бувають константи, які є загальними для класу.

Public class Program( public static void main(String args) ( double radius = 60; System.out.printf("Radisu: %f \n", radius); // 60 System.out.printf("Area: %f \n", Math.PI * radius); // 188,4 ) ) class Math( public static final double PI = 3.14; )

Варто зазначити, що протягом усіх попередніх тем активно використовувалися статичні константи. Зокрема, у виразі:

System.out.println("hello");

out представляє статичну константу класу System. Тому звернення до неї йде без створення об'єкта класу System.

Статичні ініціалізатори

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

Public class Program( public static void main(String args) ( Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 )) class Person( private int id; static int counter; static( counter = 105; ); ) public void displayId()( System.out.printf("Id: %d \n", id); ) )

Статичний ініціалізатор визначається як звичайний, тільки перед ним встановлюється ключове слово static. В даному випадку в статичному ініціалізаторі ми встановлюємо початкове значення статичного поля counter та виводимо на консоль повідомлення.

У самій програмі створюються два об'єкти класу Person. Тому консольний висновок виглядатиме так:

Static initializer Constructor Constructor Id: 105 Id: 106

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

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

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

Public class Program( public static void main(String args) ( Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 ) ) class Person( private int id; private static int counter = 1; Person()( id = counter++; ) // статичний метод ", counter); ) public void displayId()( System.out.printf("Id: %d \n", id); ) )

Тепер статична змінна недоступна ззовні, вона є приватною. А її значення виводиться за допомогою статичного методу displayCounter. Для звернення до статичного методу використається ім'я класу: Person.displayCounter() .

При використанні статичних методів треба враховувати обмеження: у статичних методах ми можемо викликати лише інші статичні методи та використовувати лише статичні змінні.

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

Public class Program( public static void main(String args) ( System.out.println(Operation.sum(45, 23))); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 ) ) class Operation( static int sum(int x, int y)( return x + y; ) static int subtract(int x, int y)( return x - y; ) static int multiply(int x, int y)( return x * y; ) )

У разі для методів sum, subtract, multiply немає значення, який саме екземпляр класу Operation використовується. Ці методи працюють лише з параметрами, не торкаючись стану класу. Тому їх можна визначити як статичні.

Змінна кількість параметрів методу

Іноді кількість аргументів, які передадуть методу, невідомо до виконання. Наприклад, вам потрібен клас, який креслить на графіку лінію, задану послідовностями х- та у-координат. Цей клас повинен містити методом, який приймає єдиний аргумент - об'єкт типу Point,представляє значення обох координат х та у. Цей метод повинен зберігати кожен об'єкт типу Pointу зв'язаному списку або в елементах масиву, поки програма, що викликає, не дасть команду на виведення всієї послідовності точок. Однак таке рішення може бути не дуже ефективним, тому що воно вимагає наявності в класі зв'язаного списку. Але ж можна було б використати єдиний метод - DrawLine,якому цей список може і не знадобитися . Цю проблему ефективно вирішує метод із змінною кількістю аргументів.

Такому методу можна задати змінну кількість аргументів через ключове слово paramsу вигляді масиву. Розглянемо приклад класу Chart,написаного на C#, що дозволяє користувачеві одним викликом отримати та вивести довільну кількість об'єктів Point:

using System;

class Point //Клас точки

public Point(int x, int y) (this.x = x; this.у = у;)

public int x; public int y;

class Chart //Клас рисувальника

public void DrawLine(Graphics g, params Point p)

Console.WriteLine("\пЦей метод дозволяє намалювати лінію " +

"за такими точками:");

for (int i = 0; i< p.GetLength(0); i++)

( Console.WriteLine("(0), (1)". p[i].x, p[i].y); )

class ChartApp

public static void Main()

Point p1 = new Point(5,10);

Point p2 = New Point (5, 15);

Point p3 = new Point(5, 20);

Chart Chart = New Chart ();

chart.DrawLine(p1, p2, p3);

Метод DrawLineповідомляє компілятор C#, що він може приймати змінну кількість об'єктів типу Point.Потім у період виконання метод використовує простий цикл forдля проходу по всіх об'єктах Pointта виведення всіх точок.

Статичним називається метод, який існує у класі як у такому, а не в окремих його примірниках. Як і у випадку інших статичних членів, головна перевага статичних методів у тому, що вони розташовані поза конкретними примірниками класу, не засмічуючи глобального простору програми. При цьому вони не порушують принципів ОВП, оскільки асоційовані з певним класом.

Визначити метод як статичний дозволяє ключове слово static.Потім для виклику методу користувач застосовує синтаксис виду Клас. Метод.Цей синтаксис необхідний, навіть якщо користувач має посилання на екземпляр класу.


Статичні ( static) методи, чи методи класу, можна викликати, не створюючи екземпляр об'єкта. Саме таким чином використовується метод Main.

public class Sample

public static int a;

public int b;

public static void DoubleA()( a *= 2; )

public void SetB()( b = a; )

public class Application

public static void Main()

Sample sc1 = новий Sample(), sc2 = новий Sample();

Sample.a = 1;

sc1.SetB();

Sample.a = 2;

sc2.SetB();

Console.WriteLine("sc1.b = (0), sc2.b = (1)", sc1.b, sc2.b);

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

То ми можемо отримати доступ до них безпосередньо через ім'я класу і оператора дозволу області видимості. Але що, якщо статичні змінні-члени закриті? Розглянемо наступний код:

У цьому випадку ми не можемо безпосередньо отримати доступ до Anything::s_value з main(), тому що цей член є private. Зазвичай доступом до закритим членам класу здійснюється через методи public. Хоча ми могли б створити звичайний метод для отримання доступу до s_value, але нам тоді довелося б створювати об'єкт цього класу для використання методу! Є кращий варіант – ми можемо зробити метод статичним.

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

class Anything (private: static int s_value; public: static int getValue() (return s_value;) // статичний метод); int Anything::s_value = 3; // Визначення статичної змінної-члена класу int main() ( std::cout<< Anything::getValue() << "\n"; }

Оскільки статичні методи не прив'язані до певного об'єкта, їх можна викликати безпосередньо через ім'я класу і оператор дозволу області видимості, їх можна викликати і через об'єкти класу (але це рекомендується).

Статичні методи не мають вказівника this *

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

По-друге, статичні методи можуть безпосередньо звертатися до інших статичних членів (змінних чи функцій), але не можуть до нестатичних членів. Це з тим, що нестатичні члени належать об'єкту класу, а статичні методи — немає!

Ще приклад

Статичні методи можна визначати поза тілом класу. Це працює так само, як і зі звичайними методами. Наприклад:

class IDGenerator (private: static int s_nextID; // оголошення статичної змінної-члена public: static int getNextID(); // оголошення статичного методу); // Визначення статичної змінної-члена знаходиться поза тілом класу. Зверніть увагу, ми тут не використовуємо ключове слово static // Починаємо генерувати ID з 1 int IDGenerator::s_nextID = 1; // Визначення статичного методу знаходиться поза тілом класу. Зверніть увагу, ми не використовуємо тут ключове слово static int IDGenerator::getNextID() ( return s_nextID++; ) int main() ( for (int count=0; count< 4; ++count) std::cout << "The next ID is: " << IDGenerator::getNextID() << "\n"; return 0; }

class IDGenerator

private :

static int s_nextID; // оголошення статичної змінної-члена

public :

static int getNextID(); // оголошення статичного методу

// Починаємо генерувати ID з 1

int IDGenerator :: s_nextID = 1;

int IDGenerator :: getNextID () ( return s_nextID ++ ; )

int main()

for (int count = 0; count< 4 ; ++ count )

std :: cout<< "The next ID is: " << IDGenerator :: getNextID () << "\n" ;

return 0;

Результат:

The next ID is: 1
The next ID is: 2
The next ID is: 3
The next ID is: 4

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

Попередження про класи з усіма статичними членами

Будьте обережні під час написання класів з усіма статичними членами. Хоча такі «чисто статичні класи» можуть бути корисними, але вони також мають недоліки.

По-перше, оскільки всі статичні члени створюються лише один раз, кілька копій «чисто статичного класу» не може (без клонування класу та її подальшого перейменування). Наприклад, якщо нам потрібні два незалежні об'єкти IDGenerator, це буде неможливо через «чисто статичний» клас.

По-друге, з уроку ми знаємо, що глобальні змінні небезпечні, оскільки будь-яка частина коду може змінити їх значення і в кінцевому підсумку змінить інші фрагменти, здавалося б, не пов'язаного коду (детальніше). Те саме справедливо і для «чисто статичних» класів. Оскільки всі члени належать класу (а чи не його об'єктам), а класи мають глобальну область видимості, то «чисто статичному класі» ми оголошуємо глобальні функції та змінні з усіма мінусами, які вони мають.

C++ не підтримує статичні конструктори

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

Якщо ваша статична змінна може бути ініціалізована безпосередньо, то конструктор не потрібен: ви можете визначити статичну змінну-член, навіть якщо вона є private. Ми робимо це на прикладі вище з s_nextID. Ось ще один приклад:

class Something (public: static std::vector s_mychars; ); std::vector Something::s_mychars = ("o", "a", "u", "i", "e"); // Визначаємо статичну змінну-член

class Something

public :

static std :: vector< char >s_mychars;

std :: vector< char >Something :: s_mychars = ( "o", "a", "u", "i", "e"); // Визначаємо статичну змінну-член

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

#include #include class Something ( private: static std::vector s_mychars; public: class _nested // визначаємо вкладений клас з ім'ям _nested ( public: _nested() // конструктор _nested ініціалізує нашу статичну змінну-член ( s_mychars.push_back("o"); s_mychars.push_back("a"); s_mychars.pus; ("u"); s_mychars.push_back("i"); s_mychars.push_back("e"); ) ); // статичний метод для виведення s_mychars static void getSomething() ( for (auto const & element: s_mychars) std::cout<< element << " "; } private: static _nested s_initializer; // используем статический объект класса _nested для гарантии того, что конструктор _nested выполнится }; std::vectorSomething::s_mychars; // Визначаємо нашу статичну змінну-член Something::_nested Something::s_initializer; // визначаємо наш статичний s_initializer, який викличе конструктор _nested для ініціалізації s_mychars int main() ( Something::getSomething(); return 0; )

#include

#include

class Something

private :

static std :: vector< char >s_mychars;

public :

class _nested // Визначаємо вкладений клас з ім'ям _nested

public :

Nested () // конструктор _nested ініціалізує нашу статичну змінну-член

s_mychars. push_back ("o");

s_mychars. push_back ("a");

s_mychars. push_back ("u");

s_mychars. push_back ("i");

s_mychars. push_back ("e");

The static can be:

Let's look at static variables and static methods first.

What is Static Variable in Java?

Статична варіація в Java є варіантом, який веде до класу і ініціалізується лише один раз при запуску execution.

  • It is a variable which belongs to the class and not to object(instance)
  • Статичні variables є initialized only once, при запуску execution. Ці variables буде initalizalized першим, перед initialization of any instance variables
  • A single copy to be shared by all instances of the class
  • A static variable can be accessed directly by the class name and doesn’t need any object

<class-name>.

What is Static Method in Java?

Статичний метод в Java є методом, який веде до класу і не до об'єкта. A static method can access only static data.

  • It is a method which belongs to the class and not to the object(instance)
  • A static method can access only static data. It can not access non-static data (instance variables)
  • Статичний метод може бути тільки одним іншим методом і не може бути нестатичний метод від нього.
  • A static method can be accessed directly by the class name and doesn’t need any object
  • Статичний метод може бути невідомим до "цього" або "суперного" ключового слова в будь-якому випадку

<class-name>.

Note: main method is static, since it must be accessible for application to run, before any instantiation takes place.

Lets learn the nuances of static keywords by doing some excercises!

Example: How to call static variables & methods

Step 1) Copy the following code into a editor

Public class Demo( public static void main(String args)( Student s1 = new Student(); s1.showData(); Student s2 = new Student(); s2.showData(); //Student.b++; //s1 .showData(); ) ) class Student ( int a; //initalizated to zero static int b; //initialized to zero only when class is loaded not for each object created. Student()( //Constructor incrementing static variable b b++ ; ) public void showData()( System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); ) //public static void increment()( //a++; //) )

Step 2) Save & Compile the code. Run the code as, java Demo.

Step 3) Expected output show below

Наведені діаграми shows, як reference variables & objects є створені і static variables accessed by the different instances.


Step 4) It is possible to access a static variable from outside the class using the syntax ClassName.Variable_Name. Uncomment line # 7 & 8 . Save, Compile & Run. Observat the output.

Value of a = 0 Value of b = 1 Value of a = 0 Value of b = 2 Value of a = 0 Value of b = 3 Step 5) Uncomment line 25,26 & 27 . Save, Compile & Run.
error: non-static variable a cannot be referenced from a static context a++;

Step 6) Error =? Це означає, що він не може бути застосований до вхідної лінії " a" від java static class method " increment".

Java Static Block

Статичний блок є блоком розміщення в Java класі, що буде виконано, коли клас є першим loaded into JVM

Class Test ( static ( / / Code goes here ) )

A static block helps to initialize the static data members, just like constructors help to initialize instance members