Java 14 is coming



Как сообщает компания Oracle, релиз Java 14 назначен на 17 марта. Интересно, связана ли дата релиза с Днем Святого Патрика (который отмечается как раз в этот день) или нет узнаем совсем скоро. Давайте посмотри на нововведения, которые будут доступны в новой джаве и решим, будем ли мы пить пиво от радости или от горя.

Records


Принципиально новая языковая фича, доступна в режиме превью в Java 14. Основная цель — избавиться от большого количества вермишели в коде. Records должны заменить классы, которые используются только для хранения данных в полях без какого-либо описанного поведения. Определим Record, а компилятор сам сгенерирует конструктор, геттеры, методы equals() и hashCode(), toString(). Где-то мы уже это видели, не так ли, господин Ломбок? Запись выглядит следующим образом:

public record Person(String name, int age){}

Для того чтобы скомпилировать Record необходимо загрузить jdk14 и ввести следующую команду:

javac —enable-preview —release 14 Person.java

Декомпилируем и посмотрим, что сделал компилятор:

public final class Person extends java.lang.Record {
    private final java.lang.String name;
    private final int age;

    public Person(java.lang.String name, int age) { /* compiled code */ }

    public java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public java.lang.String name() { /* compiled code */ }

    public int age() { /* compiled code */ }
}

Итак, вместо Record мы получили final class, который наследуется от нового, абстрактного класса Record. И как ожидалось, мы получили сгенерированные геттеры, конструктор, equals(), hashCode(), toString(). Обратим внимание на то, что все поля помечены как final, это значит, что мы не можем их переопределить, однако, сам Record не является полностью неизменяемым, т.к. объекты, которые хранятся в полях могут быть изменяемыми. Подробный разбор Record вы найдете здесь.

Разговорчивые NullPointerExceptions


Более дружелюбными станут NullPointerExceptions. Нет, компилятор все еще не умеет исправлять NPE за нас, но теперь описание исключения станет более информативным. Смоделируем ситуацию: вызовем NPE на Java 11 и Java 14. Например, у нас есть сложная композиция, типичная для Entity, и чтобы получить данные, нам нужно вызвать несколько объектов из исходного, чтобы добраться до нужного поля, и так:

var street = message.getAuthor().getAddress().getStreet();

На Java 11 мы получим старый привычный лог ошибки, который оставляет главный вопрос: Кто null? Message, Author, Address?

Exception in thread "main" java.lang.NullPointerException
	at Main.main(Main.java:11)

Чтобы запустить на Java 14, нужно скомпилировать класс так же, как и Record выше:

javac —enable-preview —release 14 Main.java

И выполнить, добавив специальный флаг:

java -XX:+ShowCodeDetailsInExceptionMessages --enable-preview Main

В результате выполнения мы получим следующий вывод:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Address.getStreet()" because the return value of "Author.getAddress()" is null
	at Main.main(Main.java:11)

Как мы видим, сообщение стало более информативным, и мы можем видеть где именно в цепочке вызовов произошел NPE.

Текстовые блоки


Текстовые блоки, появившиеся еще в Java 13, так же доступны в Java 14 как превью-фича. Напомню, что их основная задача — упростить работу с многострочными литералами. Очень удобная фича для написания SQL-запросов, HTML-кода, JSON. Думаю, что это одна из функций, которая станет очень полезной. Напомним синтаксис. Например, нам необходимо написать SQL-запрос. До Java 13, для написания запроса удобочитаемым мы бы использовали конкатенацию строк, и запрос выглядел бы примерно так:

String sql = "SELECT name, age " +
                 "FROM PERSON" +
                 "WHERE name = \'Igor\'" +
                 "AND car=\'Niva\'";

Начиная с Java 13, мы можем воспользоваться текстовым блоком, записав строку между тройными двойными кавычками вот так:


    String sql = """ 
                 SELECT name, age 
                 FROM PERSON
                 WHERE name = 'Igor'
                   AND car='Niva'
                 """;

В Java 14 добавлены два новых разделителя, которые можно использовать в текстовых блоках. Первый, это одиночный пробел: \s. Второй, это символ новой строки: \.

Switch Expressions


Начиная с Java 14, switch expressions переходит из превью-фичи в полноценную функцию. Напомним коротко особенности нового оператора:

  • Лямбда-синтаксис
  • Возможность использовать более одного выражения в case
  • Вывод ошибки в случае неполного покрытия множества возможных значений switch(). Другими словами, если вы используете перечисление:

    public enum  Car {
        NIVA, NEXIA, KIA
    }

    То если вы напишите switch() следующим образом, компилятор выдаст ошибку, которая говорит о том, что перечислены не все возможные случаи из перечисления:

    switch (car) {
        case NIVA -> System.out.println("Niva");
        case NEXIA -> System.out.println("Nexia");
    }
    // error: the switch expressions does not cover all possible input values.

  • Возможность возвращать значение:

    var avto = switch (car) {
        case NIVA, KIA -> "Niva are better";
        case NEXIA -> "Nexia";
        default -> "Niva still better";
    };


Pattern Matching


Pattern Matching новая превью-фича доступная в Java 14. О ней много говорили, её многие ждали и вот она здесь. Цель — объединить в операторе instanceof проверку типа объекта и его преобразование. Другими словами, до Java 14 мы бы писали так:

Object obj = "Igor";

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

Т.е. для того чтобы использовать методы класса, которым является объект, нужно выполнить его приведение к этому классу. Начиная с Java 14 доступен новый синтаксис, в котором instanceof объединяет в себе функции проверки и преобразования:

Object obj = "Igor";

if (obj instanceof String s){
    System.out.println(s.length());
}

Заключение


Java продолжает развиваться, упрощая жизнь простых смертных разработчиков. Новые функции призваны сделать код чище, жизнь проще, зарплаты выше. А как как думаете, какая из новых фич завоюет любовь сообщества?
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 54

    –2
    А что там с лицензией на Java?
    Она так и осталась только для некоммерческого использования?
      +1
      просто оставлю это здесь
      habr.com/ru/post/448632
        –1
        Ну оставил и что?
        В середине 2018 года Oracle объявил, что собирается изменить лицензионную политику. 16 апреля 2019 года изменение вступило в силу. Теперь все опубликованные после этой даты сборки Java SE можно использовать бесплатно только для личных нужд и с целью разработки. Для использования в коммерческих целях (в том числе для продакшена) надо оформить платную подписку у Oracle.
          –1
          дальше читать пробовали? :)
            –1
            Не поверишь. Даже в первоисточнике www.java.com/en/download/release_notice.jsp
            The new Oracle Technology Network License Agreement for Oracle Java SE is substantially different from prior Oracle Java licenses. The new license permits certain uses, such as personal use and development use, at no cost — but other uses authorized under prior Oracle Java licenses may no longer be available. Please review the terms carefully before downloading and using this product. An FAQ is available here.

              +2
              Пожалуй, прикреплю скриншотом.

                0
                Как насчет первоисточника: www.oracle.com/java/technologies/javase-jdk11-downloads.html

                До 16 апреля 2019 JDK был бесплатным для любых вариантов использования, а начиная с этой даты только для не коммерческого.


                  +3
                  JDK разные бывают. OracleJDK — лишь одна из доступных сборок OpenJDK… И да, она платная для коммерческого использования. Что не мешает использовать вам любой другой бесплатный дистрибутив JDK. Проведу аналогию с другим известным софтом.

                  RedHat Enterprise Linux можно попробовать бесплатно. Это прямо указано на сайте данного софта.

                  Ваш вопрос в этой аналогии звучал бы так:
                  А что там с лицензией на Linux?
                  Она так и осталась бесплатной только для пробного 30-дневного использования?

                    0
                    Ваша аналогия будет верна только в том случае, если бы RedHat Enterprise Linux был изначально бесплатным, а потом ему бы сменили лицензию на «не для коммерческого использования» или собирай ядро из исходников.
                      +1
                      Ну зачем собирать ядро из исходников, просто получите дистрибутив с бесплатной поддержкой у любого другого вендрора. Как и в случае с Java.
                        0
                        Тут ключевой момент — изначальный дистрибутив перестал быть бесплатным для коммерческого использования.

                        Откуда его потом брать, у другого вендора или собирать самому из исходников — совершенно другой вопрос. Как и в случае с Java.
                          0
                          в вашем изначальном сообщении ничего нет про этот ключевой момент
                            0
                            Ну как же?
                            Ваша аналогия будет верна только в том случае, если бы RedHat Enterprise Linux был изначально бесплатным, а потом ему бы сменили лицензию на «не для коммерческого использования» или собирай ядро из исходников.
        0
        Все нормально с лицензией, обычная GPL2+CE, делайте что хотите при ее соблюдении. Ну или можно приобрести право на использование конкретно оракловских билдов под оракловской лицензией в продакшене (не в продакшене можно и без покупки). Ну или покупайте саппорт не-от-оракла, если он нужен, а цены кусаются / не хочется закупаться у ораклов / нужен софт из реестра российского по (а либерика там есть).
          0
          Уточните пожалуйста, что у вас обозначают буквы "CE"
              0
              Это здорово, но к сожалению я не настолько хорошо разбираюсь в англоязычных юридических тонкостях, что бы понять отличия этой лицензии от «обычной» GPLv2.

              И судя по количеству файлов с такой модифицированной GPL (в JDK11 их почти 15000 из 65000), с этой лицензией не все так просто. Ведь Oracle вполне могла использовать «обычную» LGPL, но почему-то не сделала этого.

                0
                От GPLv2 отличается более разрешительной линковкой. От LGPL уже сложнее понять, чем отличается. Я не юрист, к сожалению.
                  0
                  Я тоже не юрист, и прежде чем отвечать на предыдущий комментарий, искал инфу в интернете.

                  GPL2+CE чаще сравнивают с более либеральной LGPL как раз за счет разрешения связывания с бинарными проприетарными компонентами. Но в отличии от LGPL, GPL2+CE не требуется обязательной передачи прав на изучение, декомпиляцию и использование патентов (при их наличии).

                  Другими словами, Oracle за счет применения GPL2+CE, не предоставляет пользователям права на изучение и декомпиляцию кода, а так же оставляется за собой право использовать код, защищенный патентами.

                  На этом, кстати, и основана её тяжба с Google.
        –8
        Слишком мало, слишком поздно. Не ясно зачем это, если есть Котлин
          +2
          По-моему в самый раз, а чем Kotlin лучше?
          В основном синтаксический сахар, а хотелось бы получше работу с нативным кодом, прекомпиляцией в ARM.
            +7
            В основном синтаксический сахар, но очень приятный.
            Попробуйте работу с коллекциями и сравните со джавовскими стримами. Стримы — ужас. Сначала сделать стрим, потом запустить коллектор — какой то дикий бойлерплейт.
            Ну или checked exceptions в лямдах.

            Но главное — корутины.
            Когда асинхронный код выглядит как синхронный это делает код очень читаемым. Без callback hell и подобной херни
              +1
              А мне нравятся стримы. Но код на котлине читать тяжко после джавового. Вероятно, дело привычки, но я так и не смог дописать свой петпроджект, глаза болят.

              Про корутины согласен, ждем релиз Loom и красивые либы на его основе…
                +1
                Стримы хороши. просто преобразование из листа в стрим и обратно мозолит глаза. Ну и методов у них намного меньше чем надо.
                0
                Так были и есть Groovy, Scala (на JDK), которые находят свою нишу и далеко не в общецелевом программировании. Сила Java в том, что он значительно синтаксически проще, чем другие jdk-языки, для обучения и, конечно, на Java просто огромное количество существующего кода.

                Лично, я бы не хотел, чтобы Java превращалась в С++, где синтаксис уже просто поборол все уровни сложности.
                  0
                  Лично, я бы не хотел, чтобы Java превращалась в С++, где синтаксис уже просто поборол все уровни сложности.
                  Эта ниша уже занята Scala
                0

                Project Panama должен войти в jdk 14, насколько я помню

                +6
                Если бы не Гугл с Андроидом, про Котлин уже бы забыли.
                  +4

                  Пилим десктоп и начинаем переписывать бэк на нэйтив, к Гуглу и Андроиду отношения не имеем.
                  Так что ваши заявления — буллщитом попахивают.

                    +4

                    Да на всех языках пишут, каждая компания упарывается как хочет. Но если бы не мобильщики, то доля Котлина болталась бы в район сотых процента. На бэке он не выстрелил.

                      –4

                      На бэке еще нет релиза, а под jvm вы можете назвать причину писать новое на java?
                      Без ломбока ясно, энтерпрайз щедро заплатит за бойлерплейт, а с ним?

                    +8

                    До того, как гугл заговорил о Котлине, на нем уже было писать куда комфортнее, чем на джаве. Если бы не заговорил, то все равно бы писали, но популярность росла бы медленнее

                      0
                      Если бы не Котлин, то неоткуда было бы криво копировать фичи и 14 релиз Java содержал бы только улучшенное сообщение для NPE. NPE, Карл.
                        +2
                        Ну действительно, ведь в Котлине уникальные фичи, которых в других языках нет)
                          0

                          Действительно, java загнивала бы и дальше, но, несомненно, была бы #1 даже оставаясь на уровне 1.6/1.8, т.к. никакие скалы и груви погоды не делали.

                    +2

                    Я как то упустил, но возможно уже обсуждали, почему сделали так, что instanceof требует отдельной именованной переменной, почему не сделали также, как в это существует в некоторых других языках, где не требуется определения нового имени?

                      0
                      Полагаю, что дело в чем-то вроде этого stackoverflow.com/a/31902768
                        +1

                        Ох, да точно. Обратная совместимость же ломается, что то я не подумал об этом сразу. Спасибо!

                      +2

                      В общем, java как-то остается в мире корпоративной разработки и не более, ибо с этими всеми приколами с синтаксисом, лицензиями, циклами релизов и прочее, новую аудиторию набрать будет сложно. Выглядит так, словно сами специально яму себе роют.

                        0
                        Ну у них есть план и они его придерживаются. ©
                        Скорее всего что не делай, всё равно джава модно-молодёжной не станет. Груз обратной совместимости тянет.

                        Что могут, то потихоньку улучшают. Если интересно, можете посмотреть вот это видео о том что там возможно грядет в ближайшие годы (а может задержится) в Java: www.youtube.com/watch?v=te3OU9fxC8U
                          +3
                          То есть новый цикл релизов и улучшения синтаксиса, по вашему, уменьшают приток новых пользователей? Раньше было лучше, с циклом релиза «ну лет через 5 выкатим, +-»?
                            0
                            Смотря, что считать новой аудиторией, возможно вы всегда работаете только на новых проектах, но по своему опыту прихожу в компании, где уже есть Java, так что можно считать новая аудитория растет засчет legacy (которого в мире более 90%).
                            +4

                            За расхождения имен генерируемых геттеров в record от спецификации JavaBeans — дизлайк: слишком много текущих версий тулзов, использующих рефлексию для доступа к данным, поломаются на record, навскидку: gradle, spring framework, jackson, hamcrest

                              0
                              Тулзы починят. А от бесполезных букв давно пора избавляться. Жабу же ругают за многословность, вот, делает шаг в верном направлении.
                                0
                                починка будет бить дополнительной просадкой производительности в рантайме, т.к. дополнительный запрос через рефлексию: а не record ли этот объект?
                              +3
                              Мне нравится когда язык развивается. Проблема в том что большинство этих версий никому не сдались. Перед тем как написать комментарий я посмотрел статистику использования различных версий java. И, как предполагал, увидел что 8 версия просто доминирует над всеми остальными ~80%. Так как язык часто используют крупные компании, банки и всякие им подобные очень сильно тормозит переход на новую версию. Конечно окончание срока поддержки наступит рано или поздно, но ведь есть ещё одна проблема. Слишком частые релизы. Кто-то скажет — что раз в пол года(LTS — раз в год) это нормально. Но для крупных компаний это создаст дополнительные проблемы, как и для поддержки зоопарка версий java.
                                +2

                                IMHO, 8 доминирует не потому что "никому не сдались" остальные, а потому что переход на версию выше приносит много боли в процессе перехода. Да даже повышение сборки JVM может принести боли, причём не сразу видимой. И да, тесты конечно решают, но всего ими не покроешь сразу


                                Свежий пример: используем Liquibase и в нём тег includeAll. На 1.8 всё работало нормально, а на 13 версии ресурсы уже не валидными считаются в Liquibase (хотя он их и находит). При этом ошибки не возникает — всё логируется как WARN.

                                  +1
                                  Они потому и не сдались, что много боли.
                                    0
                                    В принципе описанная ситуация похожа на то как переходили с 2 питона на 3 и с какими проблемами сталкивались.
                                    Опять же все мы помним сколько времени занял этот процесс
                                  0
                                  Один я не понимаю, зачем при доступе к полям записи надо писать person.name() вместо person.name? Зачем нужны дополнительные методы если они ничего не делают?
                                    0

                                    Они не ничего не делают. Так, их можно передавать как method reference.

                                      0

                                      В method reference будет два двоеточия, а в ссылке на публичное поле была бы одна точка. Второй вариант короче и понятнее. Т.к. поле финализированное, его не сломать. Так что смысл определить действительно сложно.


                                      Если бы, скажем, были стандартные геттеры и сеттеры, то можно было бы понять наличие методов как желание оставить, например, setter injection. А так стандарт (по сравнению с Lombok POJO и т.д.) сломали (нет getXXX), все финализировали (смысла нет в setXXX), но при этом логики уловить не удается. Хорошо хоть constructor остался живой, хотя и ломающий POJO. Надо думать многие JPA-реализации (и не только они) офигеют от такого финта в 14.


                                      Например, делаете вы десериализацию в бин в 100 полей. Хоть бы тем же GSONом. Это что, под все пропущенные параметры надо сначала пустые переменные посоздавать? А если они primitive? Что туда инжектировать? Сеттеров нет, не поправить потом. Не обновить даты и временные поля.


                                      В общем косяк какой-то намечается. Но попкорн недорог ).

                                        0
                                        И наследоваться не очень можно, многие фишечки спринг-даты у меня сломаются(
                                          0
                                          Так в этом же и фишка — они иммутабельные. Косяки полезут, но в основном за счет плохо продуманной архитектуры

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое