JavaRush /Курси /Java Syntax Zero /Виведення типів Java-компілятором

Виведення типів Java-компілятором

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

1. Синтаксичний цукор

Програмісти люблять, коли якийсь складний код або логіку можна написати парою рядків, і код при цьому компактний і читабельний. А розробники мов іноді допомагають їм у цьому.

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

Розробники Java зробили все, щоб усунути з Java всю можливу надмірність. Якщо у C++ щось можна зробити десятьма способами, у Java найчастіше це можна зробити лише одним способом.

Але така уніфікація не подобається ні Java-програмістам, ні творцям Java. І іноді вони спрощують життя звичайним людям, таким як ми з вами.

До речі, ви вже познайомились із річчю, яку можна віднести до синтаксичного цукру — це autoboxing і unboxing. Порівняйте:

Довгий код Компактний код
Integer a = new Integer(5);
int b = a.intValue();
Integer a = 5;
int b = a;
int b = 5;
Integer c = new Integer(b);
int b = 5;
Integer c = b;
Integer a = new Integer(1);
int b = 1;
if (a.intValue() == b)
{
   ...
}
Integer a = 1;
int b = 1;
if (a == b)
{
   ...
}

Замість довгого коду як зліва ви можете писати більш компактний код, як справа. А розумний Java-компілятор на основі короткого коду сам згенерує його повну версію. Це і є синтаксичний цукор.


2. Виведення типу змінної – var

У Java 11 компілятор став ще розумнішим і тепер може визначити тип створюваної змінної за типом значення, яке їй присвоюють. Виглядає це у коді так:

var ім'я = значення;

Де ім'я — це ім'я нової змінної, значення — її початкове значення, а var — це ключове слово, яке використовується для оголошення змінної. Тип у змінної ім'я буде такий самий, як у значення, яке їй присвоюють.

Приклади:

Як цей код бачимо ми Що бачить компілятор
var i = 1;
int i = 1;
var s = "Привіт";
String s = "Привіт";
var console = new Scanner(System.in);
Scanner console = new Scanner(System.in);
var list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<String>();
var data = new int[]{1, 2, 3};
int[] data = new int[]{1, 2, 3};

Компілятор сам визначає або, як ще кажуть, виводить тип змінної на основі значення, яке їй присвоюють.

Чимало суперечок було на тему того, чи варто додавати таку можливість у мову чи ні. Багато хто боявся, що використанням var почнуть зловживати, і читабельність коду сильно знизиться.

Частка істини в цьому є, тому краще за все використовувати var там, де це підвищує читабельність коду. Наприклад, у цих двох випадках:

Випадок 1: дивлячись на значення змінної, відразу зрозуміло, який тип у змінної

Код Пояснення
var stream = url.getInputStream();
У змінної тип InputStream
var name = person.getFullName();
У змінної тип String

А ось у цих випадках використовувати var не варто. Ну-ка, скажіть, який тип у змінної?

Код Пояснення
var result = task.execute();
Тип змінної визначити складно
var status = person.getStatus();
Тип змінної визначити складно

Випадок 2: тип змінної не важливий для розуміння коду

Часто у коді можуть бути ситуації, коли у змінної не викликаються ніякі методи – змінна просто використовується для тимчасового зберігання чогось. Використання var тут абсолютно не знижує розуміння коду:

Довгий код Компактний код
var data = stream.getMetaData();
storage.save(data)
Ми отримали метадані із потоку stream і зберегли їх у сховище storage. Який саме тип був у змінної data — не важливо.

Золота середина

Зараз наведу три способи запису одного й того ж коду. Використання var буде оптимальним варіантом.

Код Примітка
dest.writeHeaderInfo(src.getFileMetaInfo());
Занадто компактно
var headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
Ідеально
FileMetaInfo headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
Занадто детально

Коли ми перейшли від варіанту у рядку 1 до варіанту у рядку 2, ми за рахунок імені змінної (headerInfo) додали коду трохи читабельності. Тепер зрозуміло, що метод повертав не просто метаінформацію, а інформацію про заголовок.

Третій варіант був би надмірним. Ну й що, що headerInfo має тип FileMetaInfo — це й так було майже зрозуміло за методом getFileMetaInfo(). Набагато цікавіше призначення цієї метаінформації.



3. Опускання типу — оператор diamond: <>

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

ArrayList<String> list = new ArrayList<String>();

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

ArrayList<String> list = new ArrayList<>();

Як бачите, вдруге писати тип String більше не потрібно. Не так круто, як з оператором var, але свого часу і це здавалося досягненням.

Порожні трикутні дужки в типі колекції отримали назву оператор diamond: дві дужки віддалено нагадували силует діаманту.

Використовувати одночасно var і оператор diamond небажано:

var list = new ArrayList<>();

Інформація про тип, який зберігає колекція, зовсім не залишиться, і тип буде визначено як ArrayList<Object>.



4. Подвійні фігурні дужки

Пам’ятаєш швидку ініціалізацію масиву?

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

Приклади
int[] data = new int[] {1, 2, 3, 4, 5, 6, 7};
int[] data = {1, 2, 3, 4, 5, 6, 7};

Творцям Java сподобалася ідея використовувати фігурні дужки для спрощеного запису даних у масив. Але як бути з колекціями?

Для колекцій також вистачило фантазії: дозволили використовувати трюк із подвійними фігурними дужками.

З цукром Без цукру
var list = new ArrayList<String>()
{{
   add("Привіт");
   add("Як");
   add("Справи");
}};
var list = new ArrayList<String>();

list.add("Привіт");
list.add("Як");
list.add("Справи");

Якщо компілятор зустріне код у прикладі зліва, він перетворить його на код справа.

Код не стає значно компактнішим. Тут скоріше економія на дрібницях: не потрібно кожного разу писати list. Це може бути вигідно, якщо ім’я змінної дуже довге.

Але якщо ти зустрінеш у чиємусь проєкті такий код, не дивуйся 🙂


Коментарі (20)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Jaroslav Рівень 48
8 грудня 2024
Стаття про подвійні дужки І малюнок звідти:
Андрій Рівень 18
18 січня 2024
Кайф
19 листопада 2023
Профіту в подвійних дужках ніякого не бачу, тільки читабельність коду забирає, а скорочення коду мізерна
Микола Пінчук Рівень 17
7 травня 2024
+
Christopher Ward 595 Рівень 16
6 серпня 2024
Зараз тобі нема, а в взагалі має сенс, коли тобі руцями треба не 5 елементів а 50 заводити
Kostiantyn Bogatyrchuk Рівень 14 Expert
12 березня 2023
Програмісти люблять, коли якийсь складний код або логіку можна вмістити в пару рядків, і водночас код компактний і прочитний.
Roma Chernesh Рівень 16
23 січня 2023
Нове слово у статті: "метаінформація" (метадані) - це інформація, що допомогає обробляти іншу інформацію. Тобто, це вказівки, де що має знаходитися у структурі коду. Простий приклад: список глав наприкінці книги з "посиланнями" на якій сторінці, яка глава. Чи, наприклад, каталог книг у бібліотеці "Шевченко на букву Ш". У програмуванні використовується у таких випадках як автоматизація роботи програм (програма отримавши метадані, не чекає на запуск від людини, а сама обробляє інформацію і передає її іншій програмі). Чи для якогось документа метадані - це інформація "хто автор", "розмір файлу", "дата створення" та інше.
Ігор Рівень 41 Expert
9 червня 2023
простіше кажучи, метаданні - це данні про данні ( тобто, якась додаткова інформація про якусь сущність ), або частина даних з чогось. Наприклад: String string = " Hello world "; - це наші данні якщо ми візьмемо з цього тексту слово " Hello ", то це будуть метаданні змінної - string.
nveenespi Рівень 4
5 серпня 2024
Визначення вірне, тільки тут швидше за все йшлось про метадані які отримуємо з getClass();
dianosauric Рівень 42
23 вересня 2022
Я тут чай без цукру п’ю, а у кода є цукор :D
Игорь Чайка Рівень 32
3 травня 2022
У мене чомусь IntelliJ IDEA не розуміє слово var. в чому може бути проблема? я так розумію, що там java 8 використовується для ваших завдань і тому не працює?
Петро Ключук Рівень 21
17 липня 2022
Скоріш за все, довотиться здавати завдання "всліпу".
les_yeux_blancs Рівень 50
25 квітня 2023
Все він розуміє Думаю справа у тому, що ти намагався використати var у полях класу, а це робити не можна
PAMPERS Рівень 26
27 липня 2023
Онови jdk, тобі інтеліджі сама запропонує це зробити, якщо на помилці нажати alt+enter
Taras Woytowitch Рівень 16
11 січня 2022
Про ";" з подвійними фігурними дужками будьте уважні))
Харченко Иван Рівень 15
10 лютого 2022
Я, думаю, майже всі на це купились😁
Игорь Чайка Рівень 32
2 травня 2022
взагалі не побачив ";", поки комент не прочитав😀😁😂
kalkulator¹ Рівень 51
12 листопада 2022
хто ти воїн
Андрій Рівень 18
18 січня 2024
Я думав, що один на це купився😂
Володимир Рівень 26
14 березня 2025
Щоб не попадатися на таких дрібницях, треба завести звичку запускати код навіть без вимоги виводу інформації в задачі. На етапі компіляції вилізуть всі недоліки.