Java вже не та, якою була раніше. Це мова програмування, якою користуються старожили, що балакають про передні панелі з миготливими лампочками та дні дискет? Або Java все ще модна, з усіма останніми вдосконаленнями мова для інтуїтивно зрозумілого кодування та першокласної продуктивності? Можливо, Java знаходиться десь посередині: зріла мова, але молода душею.
Майже 30 років тому, 23 травня 1995 року, Java офіційно вийшла у світ. Ця мова перетворилася на одну з основ сучасного програмного забезпечення, яке працює на всьому – від крихітних сенсорних чипів до великих серверів.
Java продовжує розвиватися. Багато функцій, які живуть у великому наметі під назвою Java, відрізняються від того, що передбачалося спочатку (часто – кардинально). Програмісти створюють код, який люди 1995, 2005 чи навіть 2015 років не впізнали б, але старий код все ще працює. Це високоякісне керування. Oracle, компанія, яка придбала Sun у 2010 році, тепер регулярно постачає нові версії та додає функції, які підтримують актуальність мови Java.
InfoWorld наводить способи програмування на Java, які стали краще, аніж були раніше (і одна зміна навпаки).
Одинадцять змін у Java (переважно на краще):
- Віртуальні потоки.
- Структурований паралелізм.
- Незмінні дані.
- Збір сміття.
- Зіставлення шаблону.
- Впорядкований синтаксис.
- Запечатані класи.
- Сторонні функції та пам’ять.
- Vector API.
- Покращена нульова обробка.
- Безкоштовно, як у... платній ліцензії?
1. Віртуальні потоки
Оригінальна версія Java давала розробникам змогу створювати власні потокові об’єкти й контролювати виконання коду у багатопоточних і багатоядерних середовищах. Хоча це було краще, ніж нічого, програмісти швидко зрозуміли, що об’єкти Thread були досить великими та займали надто багато часу для створення і знищення. Створення постійного пулу потоків на початку програми стало звичайним обхідним шляхом для незграбних потоків.
Усе змінилося в Java 19 із появою віртуальних потоків. Зараз JVM виконує більшу частину роботи з розподілу системних ресурсів у програмах Java. Програмісти вказують, коли паралелізм доступний, а JVM середовища виконання виконує код одночасно, де це можливо. Віртуальні потоки є благом для сучасних архітектур, таких як мікросервіси, які легше розробляти та підтримувати.
2. Структурований паралелізм
Легкі потоки – це лише початок. Java додала абстрактну модель для паралелізму, яка полегшує програмістам і JVM одночасну обробку робочих навантажень. Нова модель структурованого паралелізму дає змогу програмісту розбивати робоче навантаження Java на завдання, які потім групуються в області. Області збираються у волокна, що працюють разом в одному потоці.
3. Незмінні дані
Створений рядок уже не можна було змінити. Виклик такої функції, як toLowerCase, створить абсолютно новий рядок. Це спростило для JVM керування безпекою та синхронізацією між потоками.
Тепер програмісти на Java можуть вказувати ті самі незмінні правила для власних об’єктів, називаючи їх «Записами». Це спрощує багатопотокову безпеку, кешування та синхронізацію. Код містить список імен і типів полів, а JVM обробляє решту.
Загальні методи, такі як equals, hashCode і toString, створюються автоматично. Решту часу JVM забезпечує незмінність записів, що спрощує багато програмних деталей і прискорює запущений код.
4. Збір сміття
Java завжди займалася багатьма деталями розподілу та відновлення пам’яті. Це функція, яку багато програмістів із задоволенням делегують JVM. Однак іноді оригінальний збирач сміття зупинявся на досить тривалий час, щоб користувачі помічали відставання продуктивності.
Сьогодні програмісти мають вибір між чотирма збирачами сміття, які використовують різноманітні алгоритми збирання сміття і спеціалізуються на різних типах програм: Garbage First (G1) Garbage Collector, Z Garbage Collector, Concurrent Garbage Collector, Parallel Collector.
Розробники не обмежуються єдиним методом збирання сміття. Крім того, їм не потрібно вдаватися до інших рішень, як-от моделювання власного керування пам’яттю шляхом повторного використання об’єктів.
5. Зіставлення шаблону за допомогою перемикача
Команда Java також удосконалила мову на деяких із найнижчих синтаксичних рівнів і надала розробникам більше можливостей для написання чіткішої та виразнішої логіки. Ключове слово switch, яке використовується для створення стеків умовних операторів if-then-else, тепер пропонує відповідність шаблону. Це означає, що логіка визначення різних випадків не обмежується базовими виразами, як-от equals.
Код Java, написаний із використанням цих шаблонів, є особливо лаконічним. Він здатний розрізняти не лише значення в даних, але й тип об’єкта. Можна використовувати всі типи посилань і нульовий покажчик. Звичайно, більш традиційна логіка із прохідною семантикою все ще підтримується, тому старий код продовжує працювати гладко.
6. Впорядкований синтаксис
На початку написання Java мало чим відрізнялася від C або C++. Фігурні дужки та крапка з комою робили майже те ж саме в Java, що й у C. Цикли були структуровані у класичній формі із трьох частин. Попри те, що його основа мала глибокий зв’язок із Lisp, базовий синтаксис Java мало чим відрізнявся від синтаксису C.
Однак останні доповнення запозичені із простоти таких мов сценаріїв, як Ruby та Python. Циклам for не потрібно прописувати кожну деталь, тому що компілятор тепер може інтуїтивно сприймати їх, коли ви циклічно переглядаєте список або масив.
Анонімні функції та лямбда-вирази також є хорошим вибором для програмістів, які хочуть зберегти натискання клавіш. Сучасні програмісти на Java можуть викладати складні структури за допомогою меншої кількості символів.
7. Запечатані класи
Із самого початку JVM була розроблена для запобігання виникненню багатьох поширених дірок у безпеці, які програмісти могли помилково залишити у своїх програмах. Останні версії додали ще більше опцій. Запечатані класи, наприклад, дають змогу творцю класу точно вказати, які класи можуть його розширити. Це не дозволяє іншим користувачам бібліотеки розширювати клас і додавати або замінювати деякі оригінальні функції.
Запечатані класи також працюють трохи швидше, аніж традиційні, оскільки вони дозволяють більш агресивну оптимізацію та вбудовування. Також вони можуть спростити відправку методів.
8. Сторонні функції та пам’ять
Віртуальна машина Java охороняє код і запобігає багатьом звичайним атакам, які можливі, коли код виконується нативно.
Для обізнаних програмістів оригінальний Java Native Interface (JNI) був чимось на кшталт чорного ходу. Команда Java знала, що деяким розробникам потрібно підключитися до бібліотек і стеків, написаних іншими мовами, і що деякі системні виклики є важливими. Тож вони відкрили цю діру у броні JVM простим попередженням про небезпеку її використання.
Тепер у нас є Foreign Function & Memory API, наразі JEP у третьому попередньому перегляді. Це API дає змогу простіше та безпечніше зв’язуватися із зовнішнім середовищем. Набагато більше роботи тепер можна писати на чистій Java: звичайні Java-програмісти почали підключатися до загальної системної пам’яті.
9. Vector API
Оригінальний клас Vector, відомий багатьом досвідченим програмістам на Java, був скоріше структурою даних, аніж математичним інструментом. Це було гнучке та синхронізоване рішення для зберігання об’єктів, яке мало чим відрізнялося від List.
Новий Vector API – це набагато більше. Це інструмент для обробки математичних даних, який стає все більш поширеним, оскільки алгоритми штучного інтелекту використовують матриці та вектори більш-менш так само, як це роблять вчені-фізики й математики.
Хороший спосіб побачити різницю між класом Vector та API – це побачити, що робить метод add. В оригінальному класі він просто закріпив об’єкт у кінці структури даних, як це робили всі інші класи Collections. В API він використовується для математичного додавання окремих елементів.
Vector API також обіцяє розкрити величезну обчислювальну потужність деяких новіших SIMD-процесорів, даючи змогу програмістам на Java створювати код, який може збивати багато довгих векторів.
10. Краща нульова обробка
Багато коду Java присвячено перевірці, подвійній перевірці, а потім потрійній перевірці об’єктів. Щоб спростити код і трохи пришвидшити роботу, Java поступово додає функції, які обробляють нульові покажчики більш витончено.
Stream API, наприклад, може обробляти довгі потоки даних і не буде зависати, якщо час від часу з’явиться нульове значення. Обгортка класу Optional може містити або не містити фактичний об’єкт, дозволяючи коду добре працювати. Якщо ви все ж хочете перевірити нуль, є оператор null-safe (?.), який перевіряє нуль дуже лаконічним способом.
11. Безкоштовно, як у... платній ліцензії?
Java завжди була практично безкоштовною, принаймні для програмістів. Із самого початку Sun хотіла залучити розробників завдяки безкоштовним інструментам й апаратному забезпеченню. У 1997 році компанія зробила сміливий крок, відкривши код для багатьох частин мови та своєї віртуальної машини. Донедавна розробники могли працювати будь-де, не заплативши ані копійки.
Тепер же картина стає туманнішою. Багато версій Java від Oracle безкоштовні, але для деяких потрібна ліцензія з дивними умовами. Здавалося б, Oracle хоче, щоб програмісти насолоджувалися свободою творити без грошових обмежень, але водночас хоче стягувати податки чи орендну плату з підприємств, які отримують значні довгострокові доходи від Java. На практиці це означає стягнення плати за те, що Oracle називає функціями підписки Java.
Отже, Java все ще безкоштовна, якщо ви не хочете оновити її для комерційного використання.
Раніше ProIT описував нові функції у Java 22.
Також ми повідомляли, що Java 18 Simple Web Server дає змогу використовувати інструмент командного рядка або API для розміщення файлів.
Підписуйтеся на ProIT у Telegram, щоб не пропустити жодну публікацію!