Ссылка для скачивания

Последнюю половину года мы подробно обсуждали здесь новшества Java 10 и знаем их наизусть.

Но было бы странно, если самая главная Java-новость за полгода не появилась бы в этом хабе.


Как говорится, просто оставлю это здесь. Вперёд к приключениям!


Действительно вышла в срок?


Да, действительно. Релиз сделали из 46 билда, и собрали день назад, глядите:


$ java -version
openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+46)
OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)

А в IDE работает, или всё красным перечёркнуто?


Работает в свежей IntelliJ IDEA. Но придётся поставить бета-версию (например, ideaIU-181.4203.400), потому что на стабильной 2017.3.5 не поддерживается этот language level.




Долгий путь к релизу


На самом деле, нет. Это самый быстрый полноценный релиз в истории!


Раньше план публиковался на странице проекта, но больше он нам не понадобится. Все этапы успешно выполнены.






И что, всё хорошо?


В основном, да. В этом релизе разработчики фокусировались на починке только тех багов, которые являются совершенно критичными для успеха Java 10. Все задачи, относящиеся к другим релизам Java, даже с высшим приоритетом, отложены.


Но какой же релиз без хорошего факапа? Тагир Валеев (lany) через считаные часы опубликовал в своём твиттере новость об эпическом новом баге в компиляторе.



Баг уже обсуждают в рассылке и ведётся работа по его починке.


Вот этот код, можно вставить и проверить:


public class Main {
    void m() {
        var s = java.util.List.of("a", 1);
    }
}

Проблема проявляется только только при включённом флаге -g, который говорит о необходимости генерации отладочной информации. В IDE он включён по-умолчанию, так что мимо ошибки не пройти :-)


Изменения, которые появились в этом релизе



JEP 286Local-Variable Type Inference.

Локальный вывод типов с помощью var. Неоднозначная фича. Регулярно вызывает бурления в рассылке.


Пример кода:


var list = new ArrayList<String>();  // infers ArrayList<String>
var stream = list.stream();          // infers Stream<String>

Бородатый анекдот в тему.
Заходит джавист в столовую и говорит: дайте, пожалуйста, Борщ борщ нью Борщ!





JEP 296: Консолидация леса исходников JDK в едином репозитории.

Широкой общественности обычно не интересно, разве что ты собираешь OpenJDK из исходников. Интересней то, что чем меньше хаоса в проекте, тем более качественный получается продукт.





JEP 304Garbage-Collector Interface.

Улучшение изоляции основных исходников от GC путём создания хорошего чистого интерфейса для GC. В последнее время стало весьма популярным писать свои GC: на подходе у нас Shenandoah, ZGC, Epsilon. Чтобы поддержать эти благие начинания, разработчикам OpenJDK пришлось конкретно разгрести свалку в коде, чтобы не только максимально упроситить создание новых GC, но и дать возможность быстро отключать ненужные GC из сборки. Один из основных критериев успеха — отсутствие просадки по перфомансу после всех этих рефакторингов.





JEP 307Parallel Full GC for G1.

CMS выбросили на мороз, и всё интересное в общеупотребительной (не низкопаузной) сборке мусора теперь происходит в G1. Читаем "Release Note: JEP 307: Parallel Full GC for G1": «Коллектор G1 создан для того, чтобы обходиться без full GC, но когда параллельная сборка не может утилизировать память достаточно быстро, происходит возвращение к full GC. Старая реализация full GC в G1 использовала однопоточный алгоритм mark-sweep-compact. После реализации JEP-307, full GC параллелизовался и стал использовать то же количество параллельных тредов-воркеров, как в young и mixed». (Напоминаю, что young GC обрабатывает только регионы young/survivor, mixed — ещё и old, full — весь хип, young/tenured).





JEP 310: Application Class-Data Sharing.

Чтобы ускорить запуск и уменьшить количество используемой памяти, предлагается расширить существующую фичу под названием Class-Data Sharing («CDS») возможностью упаковки классов в общий архив.


Если совсем коротко, то вот так архив вначале создаётся, а потом используется при запуске:


java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst -XX:SharedArchiveFile=hello.jsa -cp hello.jar

java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld




JEP 312Thread-Local Handshakes.

Возможность выполнять колбэк на тредах, не делая глобальный для JVM сейфпоинт. Фича позволяет дешёво останавливать одиночные треды, а не только «всё или ничего». Это низкоуровневая системная фича, вручную ей воспользоваться нельзя, но можно радоваться автомагически возросшей производительности программ.





JEP 313: Remove the Native-Header Generation Tool.

Утилита javah больше не нужна, потому что нативные заголовки теперь может делать javac (начиная с JDK8, на самом деле).


javah была утилитой, генерирующей сишные заголовочные файлы и исходники, необходимые для использования нативных методов. Сгенерированные ей файлы предназначены для использования в программах, написанных на Си, чтобы обращаться к экземплярам джавовых объектов из неуправляемого нативного кода. В .h-файле определяется структура, которая выглядит примерно как класс, которым мы собираемся управлять. Поля структуры — переменные экземпляра класса. Тем не мнее, в JNI использование подобных стабов не является обязательным.





JEP 314Additional Unicode Language-Tag Extensions.

Поддержка новых расширений Unicode: cu (currency type), fw (first day of week), rg (region override), tz (time zone).





JEP 316Heap Allocation on Alternative Memory Devices.

HotSpot VM теперь может выделять хиповую память на других девайсах, например, на NV-DIMM. Некоторые операционки уже умеют выделять не-DRAM память, помещая её на файловую систему, например, NTFS DAX и ext4 DAX. Добавляется опция ` -XX:AllocateHeapAt=.




JEP 317Experimental Java-Based JIT Compiler.

Graal, можно использовать как основной JIT-компилятор. Объяснять, что такое Graal — очень долго, поэтому вкратце. Под брендом Graal сейчас объединено несколько направлений: Graal Compiler, SubstrateVM, Truffle, различные языки для него ("Graal polyglot runtime"). В данном случае имеется в виду именно Compiler. На некоторых тестах, типа Scala DaCapo, грааль позволяет получить почти двухкратную производительность по сравнению с C2! Чтобы получить подобные чудесные результаты, необходимо иметь очень-очень много динамического кода и очевидно, наибольшую пользу тут извлекут программисты на Scala, Groovy, JavaScript, и т.п. Работает это чудо пока что только на 64-битных Linux и macOS.





JEP 319Root Certificates.

В JDK имеется кейстор cacerts, который нужен для хранения корневых сертификатов. Но в OpenJDK он пока пустой. Поэтому ништяки типа TLS в OpenJDK по-умолчанию не работают. Теперь этот cacerts будет правильно сконфигурирован и заполнен, и ништяки начнут работать. Кроме того, это сгладит разницу между OpenJDK и Oracle JDK.





JEP 322Time-Based Release Versioning.

Feature releases будут добавлять новые фичи. Update releases будут только чинить баги.


Ну и конечно же,


$ java -version
openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+46)
OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)



Не всё есть в JEP


В багтрекере и рассылке можно увидеть большое количество изменений, которые не получили такую широкую огласку, как основные JEP.


По этому поводу Тагир Валеев (lany) недавно написал очень хорошую статью. Дублировать её содержимое нет смысла, нужно пройти по ссылке и прочитать.


Что дальше?


Необходимо взять JDK 10 и начать миграцию на него своего кода!


Ссылка на загрузку.


Минутка рекламы. Как вы, наверное, знаете, мы делаем конференции. Ближайшая конференция по Java — JPoint 2018. Она пройдет 6-7 апреля 2018 года в Москве. В докладах часто упоминаются вопросы перехода на новые версии Java. Какие доклады там бывают — можно посмотреть в нашем архиве на YouTube или прочитать в хаброблоге. Кроме того, можно будет вживую пообщаться с докладчиками и лучшими экспертами по Java-платформе в специальных дискуссионных зонах после каждого доклада. Короче, заходите, мы вас ждём.

Комментарии (78)


  1. lany
    21.03.2018 14:17
    +1

    потому что на стабильной 2017.3.5 не поддерживается этот language level.

    Если я правильно помню, там был более хитрый алгоритм: надо просто написать var x = "foo", а когда подсветит красным, там есть квик-фикс на нём. Так-то в 2017.3 у нас уже всё работало. Но вообще да, проще на 2018.1 уже перейти.


    1. olegchir Автор
      22.03.2018 03:01


      1. Sultansoy
        22.03.2018 13:08
        +1

        А можно вашу цветовую схему узнать?


        1. olegchir Автор
          22.03.2018 16:23

          Это очень крутой плагин под названием Material Theme UI (точнее, Material Theme UI EAP по понятной причине). Оно меняет все картинки и цвета в UI. Это одна из стандартных схем, идущих с ним в коробке: Material Palenight. Там ещё несколько клёвых схем в комплекте есть!


          Очень рекомендую. Я бы на месте JB вообще поставил бы этот плагин по умолчанию, уж слишком всё няшное стаёт.


          1. tundrawolf_kiba
            22.03.2018 16:30
            +1

            Material Theme UI

            Этот кстати сейчас обновляется гораздо активнее, а EAP разработчик кажется забросил полгода назад.


            1. olegchir Автор
              22.03.2018 16:31

              Ох ничоси. Обновлюсь-ка на него.


          1. AstarothAst
            22.03.2018 16:42
            +1

            Что-то он на смену размера шрифта не реагирует…


            1. olegchir Автор
              22.03.2018 16:54

              А где меняешь? Editor -> Color Scheme -> поставить галку «Use color scheme font instead of default», выставить значение Size


              1. AstarothAst
                22.03.2018 17:18
                +1

                Да, уже нашел, спасибо!

                пока непривычно как-то :) Но няфффно, это да :D


  1. dimkss
    21.03.2018 14:22
    +4

    >> Необходимо взять JDK 10 и начать миграцию на него своего кода!
    … Эпический баг компилятора
    Вы точно уверены? ))


    1. TheKnight
      21.03.2018 14:25
      +4

      Ну дык а как еще найти все мешающие нормальным людям баги?


  1. Nagg
    21.03.2018 14:53
    +8

    Заходит джавист в столовую и говорит: дайте, пожалуйста, вар борщ нью Борщ!


    1. dskozin
      21.03.2018 15:55
      +2

      Заходит Спрингист в столовую:
      — Суп!
      — Борщ, Гороховый, Солянку?
      — NoUniqueBeanDefinitionException…


      1. tbl
        21.03.2018 16:16
        +2

        повезет ему, если будет суп дня (с аннотацией Primary)


    1. zodchiy
      21.03.2018 17:26
      +1

      удалил.


    1. xlenz
      21.03.2018 23:42

      А я рад, что наконец-то будет var вместо LinkedHashMap <String, HashMap <String, Object>> и подобного.
      Наличие вар не запрещает указывать типы там, где это нужно...


      Многословие джавы отталкивает людей, есть что улучшать, никого не обидев, сохраняя баланс


      1. st0ke
        22.03.2018 09:05
        +4

        На code-review, когда используется такой вывод типов, постоянно возникает вопрос, а подумал ли автор о типе переменной, он (тип) действительно не важен или человеку было просто лень и он «фигачил» строки одна за одной? Не знаю как в Java, а в C++ это довольно важный аспект при написании кода.

        Плюсом ещё и изобретается аналог венгерской нотации (если совсем прищуриться), когда в название переменной засовывается информация о типе (в большей мере, чем нужно).

        Нисколько не отрицаю мнения, что монстрообразные название типов действительно можно упрощать до автоматического вывода, но писать везде поголовно это опасно и нечитаемо (читаемо конечно, но времени больше тратится). В тех же плюсовых шаблонах иногда действительно лучше написать auto, а не пытаться понять, что там в итоге то должно быть.

        Многие ещё говорят, что IDE же выводит тип, только вот у вас когда определенно 10 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где, а через какое-то время повторять эту процедуру.

        Жаль, что строгость кода почему-то не находит понимание.


        1. kalininmr
          22.03.2018 11:05
          +1

          почему тип неважен?
          скорее следует понимать, что var делает такой же тип как с права.
          что и нужно в 99% процентах случаев создания объекта, где это и напрягает тавтологией.


          1. st0ke
            22.03.2018 12:20
            +2

            почему тип неважен?

            В случае, когда auto x = new Something, да, тавтология уходит, тут имелся в виду случай auto users = smth.getUsers()


            1. st0ke
              22.03.2018 12:31
              +1

              А дальше например идет foreach по этому контейнеры (то что это контейнер ясно из название функции и переменной, однако тут же вопрос, а вдруг там не линейный контейнер, а какой-то более сложный тип?)


              1. Free_ze
                22.03.2018 13:06
                +1

                однако тут же вопрос, а вдруг там не линейный контейнер, а какой-то более сложный тип?

                Названия функции-фабрики и принимающей переменной не подразумевают никакой специфики.


        1. olegchir Автор
          22.03.2018 11:07

          Я обычно пишу выражение, потом нажимаю ctrl+alt+V в Идее, запускается рефакторинг Extract Variable, и остаётся только вписать название новой переменной. То есть по сути, происходит то же самое что и с var, но убого.


          1. dpogibenko
            22.03.2018 16:24
            +1

            В Idea можно еще .var после выражения написать.


        1. Free_ze
          22.03.2018 12:12
          +1

          10 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где

          auto и var — все-таки разные вещи, хотя и юзкейсы похожи. Характерно то, что у Майерса про вывод типов отдельная глава в книжке, а про var редко где больше одного абзаца пишут.

          Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?

          Жаль, что строгость кода почему-то не находит понимание.

          Строгости кода это не мешает, зато DRY поддерживает.


          1. olegchir Автор
            22.03.2018 12:22

            Зачем типы запоминать, есть же IDE. Можно или навести мышкой с зажатым ctrl, или если не используешь мышку — нажать ctrl+Q когда переменная под курсором


            1. Free_ze
              22.03.2018 12:32
              +5

              Мышкой водить по всем переменным — тоже не самое продуктивное решение и не факт, что с тем же auto подсказка будет полезной. Да и всякие диффы смотреть в разных приложениях, которые не умеют анализировать типы в контексте проекта, будет не так удобно.

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


              1. olegchir Автор
                22.03.2018 16:26

                Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы. В частности, названия типов не должно быть частью имени метода.


                Олсо, это очень удобно, когда у тебя какой-нибудь чудовищный тип, например, лист мапов мапов мапов из листов в листы. И ты этот тип не хочешь видеть глазами, потому что он напрягает.


                1. Free_ze
                  22.03.2018 17:23
                  +1

                  Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы.
                  Я бы посмотрел на такой API, где в названиях намеренно избегают любых отсылок к типам) Шутка, я бы не хотел такого видеть никогда.
                  Если серьезно, тут уже был примерчик насчет метода getUsers(). Вам что-либо говорит это название о том, что из него можно получить?


                  1. olegchir Автор
                    22.03.2018 20:26
                    +1

                    Что угодно оно может вернуть. List, Set, Array, и даже Queue!


                    Дальше результат, скорей всего, будет итерироваться через короткую форму записи for loop. При этом знать, какой там конкретный формат хранения — не нужно, for сработает со всеми!


                    Тут можно бы спросить: а что, если getUsers() вернёт HashMap? Фокус не сработает?


                    Конечно сработает, потому что IDE-то знает о настоящем типе!


                    Как происходит итерирование в IntelliJ IDEA? Ты пишешь слово iter и нажимаешь [TAB]. Вылезает вот такая подсказка:




                    Которая после применения ведёт, например, к такой замене:




                    При этом, если там изначально была не мапа, а список, то варианты будут другие:




                    Работает ли это с var? Да, работает.




                    Работает ли это с var, который получает данные снаружи? Работает.




                    Такие дела.


                    Не нужно вводить сущности, которые не нужны. Не сломается то, чего нет.


                    В данном случае нам не нужно знать способ хранения юзеров.


                    1. Free_ze
                      22.03.2018 20:52

                      Что угодно оно может вернуть. List, Set, Array, и даже Queue!
                      Именно! Здесь будет некая Collection<User>. Не указав тип явным образом мы создали у программиста-юзера необходимую ассоциацию в терминах предметной области.
                      Тут можно бы спросить: а что, если getUsers() вернёт HashMap? Фокус не сработает?
                      Конечно нет. А какого вида хэшмап от юзеров вы себе представляете? Словарь, как правило, отражает какое-то отношение (ключ-значение, которые вряд ли будут относиться к единой сущности), а никак не множества (в математическом смысле) значений. Тогда и названия будут иными.


            1. st0ke
              22.03.2018 12:36
              +1

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


          1. st0ke
            22.03.2018 12:30
            +2

            auto и var — все-таки разные вещи, хотя и юзкейсы похожи.

            Прошу меня извинить за непонимаю, что там придумали в Java, но кажется auto просто более фунциональней, потому что можно писать, например auto * или const auto &. А так же ещё auto можно засовывать в тип аргумента функции (шаблоны для бендых) и результирующее значение. Или же я изначально не прав?

            Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?

            Запомнить в прямом смысле). Загрузить в свой мозг объект, у которого тип такой-то и согласно типу, скорее всего можно провести вот такие-то операции, такие-то операции делать оптимально (с точки зрения быстродействия), такие-то нет. Если код сложный, то спрятанный тип загружает мозг сильней, чем если бы человек не поленился и написал тип.

            Строгости кода это не мешает, зато DRY поддерживает.

            Вам тоже отмечу, что против конструкции auto x = new Something ничего против не имею. Проблема возникает, когда зовут функцию, например process, в которой название отвечает за действие, а не за тип возвращаемого значения.
            auto r = process();
            Что такое r? Какой-то результат. Не везде есть возможность и тип результата и действие уместить в одно название и неПолучитьОченьДлинноеНазваниеФункцииКотораяДелаетААвозващаетБ


            1. Free_ze
              22.03.2018 13:00
              +1

              auto просто более фунциональней

              В том и дело, результат auto не так очевиден, как с var, поэтому в C++-сообществе и бурлят споры насчет его использования в местах, где это не необходимо (локальные переменные, которые не про шаблоны). Так что, наверное, правота здесь относительна (=

              Запомнить в прямом смысле)

              Но вам же все равно придется запоминать что-то большее про тип, чем его имя, вне зависимости от использования auto, верно? А тут еще правила вывода, специфичные для auto. Потому мозг и кипит, я вас понимаю. Вывод типа тоже нужно применять с умом, ведь писать var там, где достаточно int — это оверкилл.

              например process, в которой название отвечает за действие

              Что это за результат по имени «r»? Может это errorCode или report? Согласитесь, auto report = ... лучше, чем Report r = ..., а auto errorCode=... лучше, чем int r=..., ведь потом наверняка идет что-то вроде:
              return report.isSuccess();
              // или
              if ( errorCode == PROC_SUCCESS )

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


              1. st0ke
                22.03.2018 13:49
                +2

                Что это за результат по имени «r»?

                Пардон, кусок кода был для обозначения конструкции. Однобуквенное название было лишь показатель того, что тут какой-то идентификатор.

                auto errorCode=… лучше, чем int r=...

                Все же, если там не int, а какой-то внятный enum (аля enum class в C++), то на мой взгляд ErrorCodeType error = process() лучше, чем auto errorCode = process(). Но тут уже кажется больше вкусовщина.

                Не очень хочу спорить, потому что, к сожалению, имею только два осмысленных аргумента
                1. усложняет чтение кода (скажем так, микроусложнение, но разве кто-то возразит, что его нет?).
                2. со временем отупляет и уже перестаешь задумываться, а что там за тип под капотом, что иногда приводит к очень глупым ошибкам, которые можно бы было избежать подумав, правильный ли тип у переменной: самая простая ошибка — не влезло значение, потому что auto/var вывело int32, а мы потом умножили его несколько раз или вычли из unsigned и ушли за ноль.

                Есть ещё третий момент, но он относится лишь к несовершенности IDE которыми довелось пользоваться. «Find usages» порой находит не всё (по разным причинам), а если везде указан тип, то достаточно бы было сделать grep по всем исходникам.


                1. Free_ze
                  22.03.2018 14:08
                  +1

                  усложняет чтение кода
                  Все зависит от кейса. Вы же согласились насчет Борщ борщ = new Борщ();? Так вот и я категорически против распихивания вывода типов везде, где скомпилируется.

                  со временем отупляет
                  И волосы на руках начинают расти!) Про автокомплит когда-то то же самое говорили.

                  auto/var вывело int32, а мы потом умножили его несколько раз или вычли из unsigned и ушли за ноль
                  Вы пишите выражение с каким-то параметром, если не подумали про переполнение типа, то явное его декларирование не спасет.

                  а если везде указан тип, то достаточно бы было сделать grep по всем исходникам.
                  Аргумент, вместо прямого поиска вам придется найти фабрику и грепать по ней. Хотя, это настолько же усложняет рефакторинг типа возврата.


                1. olegchir Автор
                  22.03.2018 16:28

                  со временем отупляет

                  тогда функциональное программирование — это вообще ад и содомия, мозгов не остаётся совсем!


  1. PastorGL
    21.03.2018 22:59

    Не-а, не будем мы мигрировать. Мы по старой энтерпрайзной привычке подождём LTS. Тем более, что до него недолго совсем осталось.


  1. JediPhilosopher
    21.03.2018 23:01

    Блин, что делается, куда мир летит, мы еще на 8 джаву не перешли толком (а кое-где еще и с 6 не слезли, и даже 7 еще кажется какой-то опасной новой диковиной на которую никак перекатить кучи легаси проектов не могут), а тут уже 10 выходит. Куда вообще 9 делась, я ее даже заметить не успел! Ааа, остановитесь, подождите, я не успеваю.


    1. jbaruch
      22.03.2018 02:21

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


    1. olegchir Автор
      22.03.2018 02:51

      «горшочек, не вари!»


  1. relgames
    22.03.2018 00:41

    Ну и как обычно, для многих библиотек выход новой Java — полная неожиданность.
    К примеру, Lombok не работает.


    1. lany
      22.03.2018 05:33

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


      1. olegchir Автор
        22.03.2018 05:47

        А почему они его не проапдейтили до десятки?


        1. lany
          22.03.2018 07:25
          +2

          На самом деле проапдейтили, даже в CHANGELOG написали, только поленились выпустить свежую версию почему-то. А вообще ты донат занёс людям или только требовать умеешь? ;-)


          1. lany
            22.03.2018 07:26
            +1

            Хотя, конечно, вру. "Some initial work on supporting JDK10" звучит совсем неубедительно.


            1. olegchir Автор
              22.03.2018 07:58

              Очень забавно было бы посмотреть на диффы того, что такое это «some initial work». Может быть в них есть какие-то интересные тайные аспекты интеграции с JDK.


              1. lany
                22.03.2018 07:58
                +2

                Парсинг версии пофиксали.


                1. olegchir Автор
                  22.03.2018 08:37
                  +3

                  Коммит так коммит! Можно теперь полгода отдыхать!


          1. olegchir Автор
            22.03.2018 07:57

            > А вообще ты донат занёс людям или только требовать умеешь? ;-)

            Я умею не использовать у себя Lombok! :-)

            Alt+Enter, Getter and Setter, Enter, Enter, как-то так. А ещё можно расчехлить JavaParser и переехать им исходники в цикле, если совсем ленивый.


            1. lany
              22.03.2018 07:58
              +2

              Блин, а я публичные поля оставляю просто.


              1. olegchir Автор
                22.03.2018 08:39
                +3

                А я делаю геттеры-сеттеры, потому что в течение N лет старшие товарищи били по рукам, когда пытался делать публичные поля.

                Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…


                1. Skerrigan
                  22.03.2018 09:18
                  +1

                  Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…

                  Не вы один… /смотрит с укором на половину своего кода, построенного по принципу карго-культа, вздыхает с мыслью «ну зато работает збс»...


                1. relgames
                  22.03.2018 09:47
                  +1

                  Объекты надо любить! Раз в год бывает нужда таки расширить геттер или сеттер и вставить проверку, например.


                  Насколько это оправдывает геттеры/сеттеры — хз.


                  1. olegchir Автор
                    22.03.2018 10:26

                    У меня в вебе все проверки в отдельных классах-валидаторах)


                    1. relgames
                      22.03.2018 10:31
                      +1

                      Это же не тру ООП!


                      Ну ещё ломбок генерит конструкторы, и это круто работает с новым Спрингом — можно писать private final поля, Ломбок сгенерит конструктор и спринг через конструктор вставит бины.


                      1. AstarothAst
                        22.03.2018 10:55
                        +1

                        Это же не тру ООП!

                        Почему? Наоборот, SOLID во все поля! Под задачу валидации выделен отдельный класс, который несет только одну ответственность :D


                        1. olegchir Автор
                          22.03.2018 11:09

                          тут yegor256 может рассказать, как правильно


                          1. AstarothAst
                            22.03.2018 14:40
                            +2

                            Спасибо. Не надо!


                            1. olegchir Автор
                              22.03.2018 16:29

                              Надо, Федя, надо :-)


                      1. lany
                        22.03.2018 11:48
                        +2

                        И валидацию параметров конструктора ломбок прикрутит? Если у меня class Range { private final int from, to; } и инвариант from <= to, куда мне инвариант впихнуть?


                        1. relgames
                          22.03.2018 11:55
                          +1

                          В этом случае мы пишем конструктор.
                          Ломбок — молоток, шурупы им не закручиваем.


                          Если в проекте гвоздей нет — то Ломбок и не нужен. Нам лично, в нашем проекте — он помогает.


                    1. dernasherbrezon
                      22.03.2018 12:26
                      +1

                      У меня в коде иногда бывает сначала:


                      public long getTotal() {
                           return this.number1 + this.number2;
                      }

                      А потом выясняется что нужно хранить в базе и тогда получается:


                      public long getTotal() {
                           return this.total;
                      }

                      Геттеры/Сеттеры все таки полезны. Тем более они генерируются IDE по одной кнопке.


                      1. TheKnight
                        22.03.2018 12:45
                        +1

                        Сделать правильный геттер или сеттер в случае с ломбоком не сложно. Достаточно его просто написать.
                        А в связанном коде оно и так все через геттеры и сеттеры работает.


              1. AstarothAst
                22.03.2018 10:24
                +1

                Можно я буду ссылаться на этот коммент, когда мне в следующий раз скажут, что публичные поля — это не по феншую?


                1. lany
                  22.03.2018 11:46
                  +1

                  Можно! Главное — головой думать, когда программируешь, а не фэншуем заниматься.


              1. vlanko
                22.03.2018 15:14
                +1

                в JPA… приходится гетеры, и даже конструкторы писать.


            1. relgames
              22.03.2018 09:49
              +1

              Мы начали его использовать, когда поля постоянно менялись, была такая дикая фаза. Сейчас поспокойней, но Lombok как-то прижился.


      1. relgames
        22.03.2018 10:01
        +1

        Да ладно. И ещё кучей вещей не пользоваться. Сидеть на голой джаве.


        Есть подозрение, что сломан не только Lombok. Просто он самый первый в цепочке компиляция-запуск. И дальше я пока не прошел, проще подождать немного, пока пофиксят.


        В прошлый раз, уже после выхода 9, были проблемы у jooq. Logstash вроде бы до сих пор на 9 не запускается.


        Блин, похоже, удел ынтырпрайза — LTS :(


        1. olegchir Автор
          22.03.2018 10:28

          То есть LTS — это удел ынтерпрайза, а вот юзать сырую, никем кроме трех человек не поддерижваемую штуку Lombok — это конечно ого-го удел :)


          1. relgames
            22.03.2018 10:33
            +1

            Так я же 10 для себя попробовал :)
            На личном проекте, где 9 работает.
            Но там Ломбок больше по привычке.


            На работе — 8, там Ломбок работает отлично.


  1. dougrinch
    22.03.2018 05:25

    Утилита javah больше не нужна, потому что нативные заголовки теперь может делать javac

    Очень интересно. Я правильно понимаю, что если у меня сорцы на котлине, то теперь хрен мне, а не jni? Спасибо тебе, Оракл, что заставляешь в полностью котлиновском проекте заводить единственный джавовый класс со всеми нативными методами.


    1. olegchir Автор
      22.03.2018 05:55
      +1

      Разве Котин генерит что-то специфичное для десятой жабы? А как придёт время, в JB что-нибудь придумают, наверняка у них самих external'ов дофига

      Можно попробовать выделить external методы в отдельные классы, собирать их с jvmTarget=1.8, и потом натравливать на них javac из старых версий JDK


      1. dougrinch
        22.03.2018 10:19
        +2

        Так javac же принимает на вход сорцы! И именно поэтому я не могу натравить его на котлин. В отличии от javah, которому нужны .class.


        1. olegchir Автор
          22.03.2018 10:37
          +1

          Юзай javah из старых версий JDK, его же никто не забрал :)

          Ещё тут не хватает belovrv и elizarov


          1. lany
            22.03.2018 12:04
            +2

            javah из старых версий не съест скомпилированный в новую версию класс. Впрочем, Котлин пока новее восьмёрки версии не выдаёт. Таргетить на 9-10 Котлину, наверно, смысла и нет. А вот если в 11 нестмейты выкатят, Котлин от этого выиграет.


    1. olegchir Автор
      22.03.2018 05:57

      а чойта я отвечаю, тут же специальные люди © для этого есть: sudo cast --verbose abreslav