JavaRush /Java блог /Random UA /Вийшла Java 11: нові фічі та можливості

Вийшла Java 11: нові фічі та можливості

Стаття з групи Random UA
Це раніше нові версії Java з'являлися рідко та із затримками. Тепер же Oracle успішно тримає заданий ритм «нова Java раз на півроку». Так що кілька днів тому, строго за графіком, ми отримали Java SE 11 і реалізацію JDK (Java Development Kit). Вийшла Java 11: нові фічі та можливості - 1Як завжди, нова версія буде сумісна зі старими, а підтримка Java 11 закінчиться не раніше грудня 2026 року.

Нові фічі Java SE 11 (видимі розробникам)

Нагадаємо, Java зміни вносяться за допомогою впровадження JEP «JDK Enchancement Proposal». JEP – це пропозиція щодо покращення OpenJDK, яку можуть затвердити, відкласти або відхаботи. Тобто, по суті, збірка JEP'ів є стратегією розвитку OpenJDK. У квадратних дужках перед новою фічею ми вкажемо номер відповідного JEP. [323] Local-Variable Syntax for Lambda Parameters - var-синтаксис для лямбда-параметрів Java 10 ввели ключове слово var, яке дозволяло не вказувати явно тип локальної змінної. Це спрощує код. JEP 323 розширює можливості використання такого синтаксису по відношенню до лямбда-виразів. Простий приклад:
list.stream ()
                 .map ((var s) -> s.toLowerCase ())
                 .collect (Collectors.toList ());
Як пише Саймон Ріттер , відомий Java-євангеліст, досвідчений Java-програміст помітить, що використання var в даному випадку може бути зайвим, оскільки код вище можна замінити наступним:
list.stream ()
                  .map (s -> s.toLowerCase ())
                  .collect (Collectors.toList ());
Навіщо, у такому разі, підтримувати var? Просто є один особливий випадок - коли ви хочете додати інструкцію до лямбда-параметру. Це неможливо зробити без будь-якого типу, і щоб не використовувати явний тип, ми можемо спростити все за допомогою var наступним чином:
list.stream ()
                 .map ((@ Notnull var s) -> s.toLowerCase ())
                 .collect (Collectors.toList ());
[330] Launch Single-File Source-Code Programs Удосконалення Java-лаунчера для запуску програми у вигляді єдиного файлу з Java-вихідниками Java часто критикують за багатослівний синтаксис і багатоступінчасту «церемонію» запуску навіть тривіальної програми. Іноді це відлякує новачків. Для написання програми, яка просто друкує Hello World! », потрібно написати клас із загальнодоступним статичним voidосновним методом та використовувати метод System.out.println. Зробивши це, ви повинні скомпілювати код за допомогою javac . Нарешті, після цього ви можете запустити програму, яка виведе злощасне вітання (зрозуміло, інтегроване середовище розробки як IDEA , так і вбудоване в JavaRush, Виконує цю «магію запуску програми» самостійно - прим. ред.). Будемо відвертими: у більшості мов програмування реальний сценарій запуску програм виглядає набагато простіше. JEP 330 усуває необхідність компіляції однофайлової програми, тому тепер, якщо ви користуєтеся командним рядком, просто введіть
java HelloWorld.java
Лаунчер Java визначить, що файл містить вихідний код Java і скомпілює код у файл класу перед його виконанням. Після або до імені файлу з вихідним кодом можна розмістити параметри. Ті, що поміщені після імені, передаються як параметри під час виконання програми. Ті, що розміщені до імені, передаються як параметри лаунчеру Java після компіляції коду. Параметри, що стосуються компілятора (наприклад, шлях до класів), також передадуть javac для компіляції. приклад. Рядок:
java -classpath / home / foo / java Hello.java Bonjour
буде еквівалентна таким рядкам:
javac -classpath / home / foo / java Hello.java
java -classpath / home / foo / java Hello Bonjour
[321] HTTP Client (Standard) - підтримка HTTP Client API стандартизована У JDK 9 був представлений новий API для підтримки протоколу HTTP Client (JEP 110) . Оскільки в JDK 9 також впровадабо платформу Java Platform Module System (JPMS) , цей API був включений як інкубаторний модуль (це модулі для надання розробникам нових API, які ще не стали стандартом Java SE, тоді як «діючі» API готуються до видалення розробники можуть випробувати нові API та спробувати забезпечити зворотний зв'язок). Після внесення необхідних змін (це API було оновлено в JDK 10), API може стати частиною стандарту. Так ось, API HTTP Client тепер офіційно входить до Java SE 11. Це вводить новий модуль та пакет для JDK, java.net.http . Основні нові типи: HttpClient HttpRequest HttpResponse WebSocket Цей API можна використовувати синхронно або асинхронно. В асинхронному режимі використовуються CompletionFuturesі CompletionStages. [320] Remove The Java EE та CORBA Modules — видалені модулі Java EE та COBRA Разом із впровадженням платформи Java Platform Module System (JPMS) у дев'ятій версії Java, з'явилася можливість розділити монолітний файл rt.jarна кілька модулів. Крім того, JPMS дозволяє створити середовище виконання Java, яке включає тільки модулі, необхідні для вашої програми, що суттєво зменшує її розмір. З прозоро визначеними межами модулів стало набагато простіше видалити застарілі частини Java API - ось що робить JEP 320. Метамодуль java.se.ee включає шість модулів, які не будуть входити в стандарт Java SE 11 і не будуть включені в JDK:
  • corba
  • transaction
  • activation
  • xml.bind
  • xml.ws
  • xml.ws.annotation
Ці модулі оголосабо застарілими (deprecated) ще JDK 9, і не були включені за умовчанням в компіляцію або виконання. Це означає, якщо ви намагалися скомпілювати або запустити програму, яка використовує API цих модулів на JDK 9 або JDK 10, у вас нічого не вийшло. Якщо ви використовуєте API цих модулів у своєму коді, вам потрібно буде надати їх у вигляді окремого модуля або бібліотеки.

Нові API

Велика кількість нових API у JDK 11 з'явилася завдяки включенню до стандарту мови модуля HTTP Client та Flight Recorder . З повним списком API можна ознайомитись у наступному повному та ґрунтовному порівнянні різних версій JDK , складеному Гуннаром Морлінгом. А в цій замітці перерахуємо деякі нові методи, які не входять до модулів java.net.http , jdk.jfr та java.security . java.lang.String Можливо, зміна в String є одним з найважливіших в API JDK 11. Тут є кілька корисних нових методів.
  • boolean isBlank (): повертає true, якщо рядок порожній або містить лише пробіли, інакше false.

  • Stream lines(): повертає потік рядків, витягнутих із цього рядка, розділених термінаторами рядків.

  • String repeat (int): повертає рядок, значення якого є конкатенацією цього рядка, що повторюється int разів.

  • String strip (): Повертає рядок, з якого видалено всі пробіли, які знаходяться до першого символу, що не є пробілом, або після останнього.

  • String stripLeading (): Повертає рядок, з якого видалено всі пробіли, які знаходяться до першого символу, що не є пробілом.

  • String stripTrainling (): Повертає рядок, з якого видалено всі пробіли, які знаходяться після останнього символу, що не є пробілом.
Щось схоже на strip()вже робив метод trim (), тільки ось під пробілами ці методи розуміють різні речі. У разі trim()відсікаються тільки прогалини, а в strip()ще й спецсимволи, на зразок табуляції. java.lang.StringBuffer java.lang.StringBuilder Обидва ці класи містять новий метод compareTo (), який приймає StringBufferі StringBuilderповертає int. Метод лексичного порівняння аналогічний новому методу compareTo() CharSequence. java.io.ByteArrayOutputStream
  • void writeBytes (byte []): записує всі байти параметра у вихідний потік java.io.FileReader
Тут з'явабося два нові конструктори, які дозволяють вказати Charset. java.io.FileWriter Чотири нові конструктори, які дозволяють вказати Charset. java.io.InputStream
  • io.InputStream nullInputStream (): повертає InputStream, який не зчитує байти Як використати цей метод? Можете вважати його чимось на кшталт /dev/null для викидання непотрібного вам висновку чи запровадження введення, який завжди повертає нуль байтів.
java.io.OutputStream
  • io.OutputStream nullOutputStream ()
java.io.Reader
  • io.Reader nullReader ()
java.io.Writer
  • io.Writer nullWriter ()
java.lang.Character
  • String toString (int): це перевантажена форма існуючого методу, але замість char використовується int.
java.lang.CharSequence
  • int compare (CharSequence, CharSequence)CharSequence: лексикографічно порівнює два екземпляри Повертає негативне значення, нуль або позитивне значення, якщо перша послідовність лексикографічно менша, дорівнює або більше другої, відповідно.
java.lang.ref.Reference
    lang.Object clone (): євангеліст Java Саймон Ріттер зізнається, що цей метод його бентежить Клас Referenceне реалізує інтерфейс Cloneable, і цей метод завжди генеруватиме виняток CloneNotSupportedException. Проте експерт припускає, що цей метод стане в нагоді для чогось у майбутньому.
java.lang.Runtime java.lang.System Тут нових методів немає. Згадаємо лише, що метод runFinalizersOnExit ()видалений з обох цих класів, що може спричинити проблеми із сумісністю. java.lang.Thread Ніяких додаткових методів, згадаємо тільки, що destroy ()і stop (Throwable)були видалені. Однак stop (), який не приймає аргументів, все ще є. Пам'ятайте про це, оскільки цілком можливі проблеми із сумісністю. java.nio.ByteBuffer java.nio.CharBuffer java.nio.DoubleBuffer java.nio.FloatBuffer java.nio.LongBuffer java.nio.ShortBuffer У всі ці класи розробники мови додали метод mismatch (), який знаходить і повертає відносний індекс першого та заданим буфером. java.nio.channels.SelectionKey
  • int interestOpsAnd (int)

  • int interestOpsOr (int)
java.nio.channels.Selector
  • int select (java.util.function.Consumer, long): вибирає та виконує дію на клавішах, відповідні канали яких готові для операцій введення-виведення. Параметр long – це тайм-аут.

  • int select (java.util.function.Consumer): працює як метод вище, тільки без таймууту

  • int selectNow (java.util.function.Consumer): працює як метод вище, тільки він non-blocking.

java.nio.file.Files
  • String readString (Path): зчитує весь контент з файлу в рядок, декодуючи байти символи з використанням кодування UTF-8 .

  • String readString (Path, Charset): працює як метод вище, тільки декодує байти символи за допомогою Charset.

  • Path writeString (Path, CharSequence, java.nio.file. OpenOption []): якщо записуватиме послідовність символів CharSequenceу файл, ці символи будуть закодовані в байти (за допомогою UTF-8 ).

  • Path writeString (Path, CharSequence, java.nio.file. Charset, OpenOption []): працює, як метод вище, тільки кодування символів у байти здійснюється за допомогою Charset.
java.nio.file.Path
  • Шлях (String, String []): повертає шлях (Path), перетворюючи рядок колії або послідовність рядків, які при об'єднанні утворюють рядок колії.

  • Шлях (net.URI): повертає шлях, перетворюючи URI.
java.util.Collection
  • Object [] toArray (java.util.function.IntFunction): повертає масив, що містить всі елементи в цій колекції, використовуючи надану генераторну функцію для розподілу масива, що повертається.
java.util.concurrent.PriorityBlockingQueue java.util.PriorityQueue
  • void forEach (java.util.function.Consumer): виконує задану дію для кожного елемента Iterable доти, доки всі елементи не будуть оброблені, або дія не викличе виняток.

  • boolean removeAll (java.util.Collection): видаляє всі елементи цієї колекції, які також містяться у вказаній колекції (додаткова операція).

  • boolean removeIf (java.util.function.Predicate): Видаляє всі елементи цієї колекції, які задовольняють заданий предикат.

  • boolean retainAll (java.util.Collection): Зберігає лише елементи цієї колекції, які містяться у вказаній колекції (додаткова операція).
java.util.concurrent.TimeUnit
  • long convert (java.time.Duration): конвертує задану тривалість часу в цей юніт
java.util.function.Predicate
  • Predicate not(Predicate): повертає предикат, який є запереченням поставленого предикату
Наприклад, наступний код:
lines.stream ()

.filter (s ->! s.isBlank ())
можна перетворити на такий:
lines.stream ()

.filter (Predicate.not (String :: ISBLANK))
а якщо ми використовуємо статичний імпорт, то ось що ми отримаємо:
lines.stream ()
.filter (not(String :: ISBLANK))
java.util.Optional java.util.OptionalInt java.util.OptionalDouble java.util.OptionalLong
  • boolean isEmpty (): Якщо значення відсутнє, повертає true , інакше false .
java.util.regex.Pattern
  • Predicate asMatchPredicate (): експерт Java Саймон Ріттер вважає, що тут може бути прихований справжній скарб API JDK 11. Цей метод створює предикат, який перевіряє, чи відповідає цей шаблон заданому рядку введення.
java.util.zip.Deflater
  • int deflate (ByteBuffer): стискає вхідні дані та заповнює вказаний буфер стислими даними.

  • int deflate (ByteBuffer, int): стискає вхідні дані та заповнює вказаний буфер стислими даними. Повертає фактичну кількість стислих даних.

  • void setDictionary (ByteBuffer): встановлює заданий словник для стиснення байти в даному буфері. Це перевантажена форма існуючого методу, який тепер може приймати ByteBuffer, а не байтовий масив.

  • void setInput (ByteBuffer): Встановлює вхідні дані для стиснення. Також є перевантаженою формою наявного методу.
java.util.zip.Inflater
  • int inflate (ByteBuffer): розпаковує байти у вказаний буфер. Повертає фактичну кількість стиснених байтів.

  • void setDictionary (ByteBuffer): встановлює заданий словник байти в даному буфері. Є перевантаженою формою наявного методу.

  • void setInput (ByteBuffer): встановлює вхідні дані для декомпресії Перевантажена форма наявного методу.
javax.print.attribute.standard.DialogOwner Це новий клас в JDK 11 і він є класом атрибутів, який використовується для підтримки запитів на сторінку друку або налаштування, повинен відображатися поверх всіх вікон або певного вікна. javax.swing.DefaultComboBoxModel javax.swing.DefaultListModel
  • void addAll (Collection): додає всі елементи в колекції.

  • void addAll (int, Collection): додає всі елементи, які є в колекції, починаючи з зазначеного індексу.
javax.swing.ListSelectionModel
  • int [] getSelectedIndices (): повертає масив усіх вибраних індексів у вибраній моделі у порядку зростання.

  • int getSelectedItemsCount (): повертає кількість вибраних елементів.
jdk.jshell.EvalException
  • shell.JShellException getCause (): повертає причину throwable у виконуючому клієнті, представленому цим EvalException, або null, якщо причини не існує або вона невідома.

Недевелоперські фічі Java 11

[181] Nest-Based Access Control Java та інші мови підтримують вкладені класи через внутрішні класи. Щоб це працювало, компілятор повинен виконати певні трюки. Наприклад:
public class Outer {
    private int outerInt;

     class Inner {
       public void printOuterInt() {
         System.out.println("Outer int = " + outerInt);
       }
     }
   }
Компілятор модифікує це, щоб створити перед виконанням компіляції щось на зразок такого:
public class Outer {
      private int outerInt;

      public int access$000() {
        return outerInt;
      }

    }


    class Inner$Outer {

      Outer outer;

      public void printOuterInt() {
        System.out.println("Outer int = " + outer.access$000());
      }
    }
Хоча за логікою внутрішній клас є частиною того самого коду, що і зовнішній клас, він скомпільований як окремий клас. Тому для цієї операції потрібен синтетичний з'єднувальний метод, який повинен створити компілятор для забезпечення доступу до private -поля зовнішнього класу. Цей JEP є концепцією вкладень (гнізд), де два члени одного вкладення (Outer and Inner з нашого прикладу) є «друзями по вкладенню». Для формату файлу класу визначено два нові атрибути - NestHost і NestMembers . Ці зміни корисні для інших мов, які підтримують вкладені класи та байткод. Ця функція представляє три нові методи для java.lang.Class : Class getNestHost () Class [] getNestMembers () boolean isNestmateOf (Class) [309] Dynamic Class-File Constants Цей JEP описує розширення формату файлу класу підтримки нової форми з постійним пулом CONSTANT_Dynamic. Ідея динамічної константи здається оксюмороном, але, по суті, ви можете думати про неї як про кінцеве значення Java 11. Значення константи-пулу не задано під час компіляції (на відміну від інших констант), але використовує метод початкового завантаження для визначення значення в час виконання. Тому значення є динамічним, але оскільки його значення задано лише один раз, воно також є постійним. Ця функція в першу чергу націлена на людей, які розробляють нові мови та компілятори, які генеруватимуть байт-коди та файли класів як висновок для запуску на JVM. [315] Improve Aarch64 Intrinsics Цей JEP запропонував співтовариство Red Hat. Тепер JVM може використовувати більше спеціалізованих інструкцій, доступних у наборі команд Arm 64. Зокрема, це покращує роботу методів sin ()і класу java.lang.Math . [318] Epsilon: A No-Op Garbage Collector Як і у випадку JEP 315 , за появу збирача сміття Epsilon можете дякувати Red Hat. Epsilon незвичайний хоча б тим, що насправді він не збирає сміття! При створенні нових об'єктів він виділяє пам'ять, якщо це потрібно, але не відновлює простір, зайнятий незареєстрованими об'єктами. « І в чому сенс? », - Запитайте ви. Виявляється у такої «складання сміття» є два види використання: cos ()log ()
  1. Насамперед цей збирач сміття призначений для того, щоб нові алгоритми GC були оцінені з точки зору їх впливу на продуктивність. Ідея полягає в тому, щоб запустити приклад програми з Epsilon та згенерувати набір показників. Включається новий алгоритм складання сміття, запускаються самі тести, та був результати порівнюються.

  2. Для дуже коротких завдань (вважайте безсерверні функції у хмарі), де ви можете гарантувати, що не перевищите пам'ять виділену купі. Це може підвищити продуктивність за рахунок відсутності накладних витрат (включаючи збирання статистики, необхідної для ухвалення рішення про запуск колектора) у коді програми. Якщо простір купи вичерпано, JVM може бути налаштований з помилкою одним із трьох способів:
    • Викликається звичайний OutOfMemoryError.
    • Виконати скидання купи
    • Збій жорсткого диска JVM і, можливо, виконання іншого завдання (наприклад, запуск відладчика).
[328]: Flight Recorder Flight Recorder – це низькорівнева структура збору даних для JVM. До JDK 11 це була комерційна функція Oracle JDK binary. Тепер Oracle усуває функціональні відмінності між Oracle JDK та одним білдом із OpenJDK. Ось що робить Flight Recorder :
  • Надає API для виробництва та споживання даних як подій
  • Надає буферний механізм та формат двійкових даних
  • Дозволяє налаштування та фільтрацію подій
  • Надавати події для ОС, JVM HotSpot та бібліотек JDK
Цей JEP присвячений оновленню шифрів , що використовуються JDK. В даному випадку реалізовані алгоритми шифрування ChaCha20 і ChaCha20-Poly1305 , як зазначено в RFC 7539. ChaCha20 - це відносно новий потоковий шифр, який може замінити старий небезпечний шифр RC4 . [333] ZGC: A Scalable Low-Latency Garbage Collector Експериментальний масштабувальник сміття з низькою затримкою. Призначений для використання з додатками, для яких потрібна велика (багатогігабайтна) купа і низька затримка. Він використовує купу одного покоління та виконує більшість (але не всі) роботи зі складання сміття одночасно з додатком. [332] Transport Layer Security (TLS) 1.3 TLS 1.3 (RFC 8446) - серйозна латка протоколу захисту транспортного рівня TLS, яка забезпечує значне підвищення безпеки та продуктивності порівняно з попередніми версіями. JDK тепер підтримує цю версію протоколу. Матеріал заснований на статті Саймона Ріттера та офіційної документації .
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ