JavaRush /Курси /Java Syntax Zero /Нюанси роботи з змінними

Нюанси роботи з змінними

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

1. Константи

У багатьох мовах програмування є константизмінні, значення яких не можна змінювати. Зазвичай це якісь фундаментальні речі типу числа Pi або кількості днів у місяцях. Хоча, в принципі, програміст може зробити будь-яку змінну константою, якщо вирішить, що це необхідно.

Отже, як же оголосити незмінну змінну (константу) в Java? Для цього є спеціальне ключове слово — final. Виглядає створення незмінної змінної так само, як і створення звичайної, тільки перед типом змінної потрібно написати слово final:

final тип ім'я = значення;

Якщо ви спробуєте присвоїти final-змінній інше значення, ваша програма просто не скомпілюється.

final-змінну обов'язково потрібно ініціалізувати при оголошенні (присвоїти їй значення). У цього правила є одне виключення: можна перенести ініціалізацію змінної класу в конструктор. Але про це ви дізнаєтеся на 10-му рівні.

Щоб зменшити кількість ключових слів, розробники Java використовують слово final не тільки для оголошення констант. final також може бути вказано перед методом і навіть класом. Методи, оголошені як final, не можна перевизначати (override), а від класу, оголошеного як final, не можна наслідуватись.

Модифікатор final можна додавати перед будь-якими змінними: локальними, параметрами, полями класу і статичними змінними.

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

Приклад:

final int[] data = {1, 2, 3, 4, 5, 6};

data = new int[]{6, 7, 8, 9};

data[0] = 0;
data[1] = 0;
data[2] = 0;
Створюємо масив.

Так не можна: змінна data оголошена як final.

А так можна.
І так можна.

Глобальні константи

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

Приклади:

class Solution
{
   public static final String SOURCE_ROOT = "c:\\projects\\my\\";
   public static final int DISPLAY_WIDTH = 1024;
   public static final int DISPLAY_HEIGHT = 768;
}


2. Затінення змінних

Як ми вже казали раніше, не можна в одному методі створити кілька локальних змінних з однаковими іменами. У різних методах — можна.

Але ось те, чого ви, швидше за все, не знаєте: дозволяється, щоб у змінних класу і локальних змінних методу були однакові імена.

Приклад:

Код Доступність змінних
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     sum = sum + data;
     int sum = data * 2;
     count++;
   }
}


count
count, sum
count, sum
count, sum
count, sum, data
count, sum, data
count, sum, data
count, sum, data
count, sum

У методі add ми оголосили локальну змінну sum, і вона до кінця дії методу перекриває (або ще кажуть затінює) собою змінну класу sum.

Ну ок, скажете ви, навіть у якомусь сенсі очікувана поведінка. Але це ще не все. Виявляється, якщо змінну класу затінює локальна змінна, в методі все-таки існує спосіб звернутися до змінної класу. Для цього потрібно перед її ім'ям написати ключове слово this:

this.ім'я

Ось приклад, де конфлікт імен успішно вирішується:

Код Доступність змінних
public class Solution
{
   public int count = 0;
   public int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     this.sum = this.sum + data;
     count++;
   }
}


this.count
this.count, this.sum
this.count, this.sum
this.count, this.sum
this.count, this.sum, data
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum, data, sum
this.count, this.sum

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

Якщо затінюється не просто змінна класу, а статична змінна класу, звертатися до неї потрібно не через this, а через ім'я класу:

ClassName.ім'я

Приклад:

Код Доступність змінних
public class Solution
{
   public static int count = 0;
   public static int sum = 0;

   public void add(int data)
   {
     int sum = data * 2;
     Solution.sum = Solution.sum + data;
     count++;
   }
}

Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum
Solution.count, Solution.sum, data
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum, data, sum
Solution.count, Solution.sum

Усі статичні змінні count і sum доступні як із префіксом у вигляді імені класу Solution, так і без нього. У тих рядках, де локальна змінна sum затінює змінну класу sum, доступ до змінної класу sum можливий тільки при використанні префікса Solution.



3. Змінні всередині циклу for

І ще один маленький, але цікавий факт.

Є ще місце, де особливим чином оголошується змінна — це цикл for.

Якщо ти пам’ятаєш, зазвичай у циклу for в круглих дужках оголошується змінна-лічильник. І яка ж буде видимість цієї змінної? Вона ж не знаходиться в тілі циклу — значить, весь метод? Або ж все-таки ні?

Правильна відповідь така: змінна, оголошена в заголовку циклу for, видна тільки в тілі циклу і в заголовку циклу for.

Приклад:

Код Доступність змінних
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   System.out.println("кінець");
}


a
a
a, i
a, i
a, i
a
a
a

Тому ти завжди можеш у своєму коді послідовно написати кілька циклів із змінною-лічильником з однаковим ім’ям — проблем не виникне.

Приклад:

Код Доступність змінних
public static void main(String[] args)
{
   int a = 0;

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   for (int i = 0; i < 10; i++)
   {
     System.out.println(i);
   }

   System.out.println("кінець");
}


a
a
a, i
a, i
a, i
a
a
a, i
a, i
a, i
a
a
a


Коментарі (16)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Dmytro Рівень 26
15 червня 2024
с каких пор население - это константа???
Ян Третьяк Рівень 29
12 грудня 2023
Не розумію нащо цей приклад:

final int[] data = {1, 2, 3, 4, 5, 6};

data = {6, 7, 8, 9};

data[0] = 0;
data[1] = 0;
data[2] = 0;
На скільки я розумію (навіть спробував), якщо ми вже оголосили масив, без "final", то ми не можемо просто взяти і написати що він тепер буде з іншими значеннями, а тим паче іншого розміру. Чи я щось не догоняю?
De Stroy Рівень 10
6 квітня 2024

int[] data = new int[] {1, 2, 3};
data = new int[] {3, 4, 5, 6};
System.out.println(Arrays.toString(data));
Без final, можемо сказати, що data посилається на новий масив іншого розміру. Якщо поставити final, то буде помилка при компіляції.
Alex Рівень 2
18 серпня 2024
простіше кажучи: змінна data містить в собі не масив, а ПОСИЛАННЯ на нього в пам'яті. Це означає що ти не можеш змінити саме ПОСИЛАННЯ, але сам масив на яке це посилання вказує - змінити можна. В банці з-під огірків листок з адресою, куди поклали огірки. Якщо ця банка створена з final - ти не можеш змінити листок з адресою, але ти завжди можеш глянути на листок, піти за вказаною адресою і взяти собі огірок
7 травня 2023
В першому завданні трохи не зрозуміла, вказано в лекції, що статичні константи зазвичай називаються великими буквами, але в самому завданні статична константа з великими буквами не приймається. То все ж, яка різниця? Чому одні можна називати великими, а інші ні?
Василь Рівень 4
22 липня 2023
це всього забаганки місцевого валідатора. Не звертайте увагу. Але я думаю що на 10 левелі ви вже і самі до цього дійшли )
Denis Polyak Рівень 51
31 березня 2023
АХАХАХА з яких пір популяція (населення планети) це стала велечина?
Kostiantyn Bogatyrchuk Рівень 14 Expert
22 січня 2023
от читаю і не розумію, чому не подавалося цієї нформації раніше, коли нам подавали інформацію про типи змінних. Скільки разів бувало, що я оголошував змінні у коді і не міг зрозуміти чому при компіляції виникає конфлікт.
Roma Chernesh Рівень 16
17 грудня 2022
Хто розуміє, чом у статичному методі main ми можемо використовувати нестатичні змінні?
les_yeux_blancs Рівень 50
20 квітня 2023
можна приклад?
Roma Chernesh Рівень 16
10 травня 2023
Так! Наскільки розумію, що у static методы змінні можуть бути будь-які: public static void main(String[] args) { int a = 0; for (int i = 0; i < 10; i++) { System.out.println(i); } System.out.println("end"); }
les_yeux_blancs Рівень 50
10 травня 2023
Так це внутрішні змінні метода, а не поля класу, тут потрібно розрізняти Все, що є оголошеним усередині методу, є доступним лише для цього методу, створюється кожен раз заново при його виконання й видаляється після
Pan Vitali Moroz Рівень 51
12 вересня 2022
Дякую, цікаво
YPon Рівень 22
12 вересня 2021
this.salary = this.salary + salary; Так лучше))
Харченко Иван Рівень 15
2 лютого 2022
Мабуть, малося на увазі, що в метод setSalary подається не те, на скільки змінилася зарплата, а змінна int salary - яка просто вказує нову зарплату. а так вийде, була в мене зарплата 1000, мені збільшили її на 200, начебто непогано, тепер вона в мене 1200. Але ні, слава програмістам, зарплата стала this.salary = this.salary + salary, тобто 1000 + 1200, тобто 2200, але, я вважаю, шеф буде проти🤣
Me Lex Рівень 12
15 березня 2022
Не зовсім ) Бо зарплата не змінить а збільшиться ) Якщо ти працівник то буде не погано Але роботодавець не оціне :D