Здравствуй, Хабр. Как ты помнишь, недавно произошёл официальный релиз Java 10. Учитывая, что практически все сейчас используют преимущественно 8-ку, с выходом 10-ки нас ждут такие вкусности как модульность (вошла в 9-ку) и local variable type inference. Звучит неплохо, можно попробовать поэкспериментировать с переносом какого-нибудь существующего проекта на 10-ку.

image

О том, какие разновидности боли ждут нас, можно узнать под катом.

Я просто оставлю это здесь не преследую цели изложить здесь все возможные проблемы с миграцией java-проектов с 8-й версии Java на 9-ю или 10-ю. Хочется зафиксировать свой небольшой опыт первого контакта с новыми версиями Java как-то кроме как в устных обсуждениях с коллегами. Возможно он кого-то остановит кому-то окажется полезен.
image


Для начала, IDEA версии 2018.1 отказалась работать на JVM версий 9 и 10 причём на 2-х разных машинах. Выглядело это как отсутствие части элементов GUI и отсутствие темы для части из оставшихся элементов. Это было небольшой проблемой, так как IDEA можно указать конкретную JVM для запуска.

1. Проблемы с реализацией модульности


Для начала давайте сделаем наше приложение модульным (не зря же разработчики JDK старались и страдали над проектом Jigsaw)?

1.1. Проблемы с утилитой jdeps


Чтобы из существующей иерархии классов получить модуль java, нам потребуется:

  • написать 1 или несколько файлов module-info.java с указанием в них имен модулей, зависимостей и экспортируемых пакетов
  • добавить аргументы для компилятора (--module-path и прочие)

image

Вроде бы выглядит всё довольно просто на первый взгляд.

1.1.1. Зависимости от внешних библиотек больше не работают без специальных заклинаний


Ничего просто не соберётся. Если вы хотите собрать модульно приложенье, то ваши зависимости также должны быть модульны. Иначе просто не получится добавить их в module-info.java. Точнее добавить-то можно — старомодные jar-файлы библиотек рассматриваются как так называемые «автоматические модули». Однако, проблема в том, что автоматические модули при сборке использовать нельзя. Да, в популярных репозиториях пока что очень мало библиотек, собраных в качестве модулей и вы просто не сможете их использовать. Nobody cares.

Здесь-то и понадобилась утилита jdeps, которая может проанализировать jar-файл и сгенерировать module-info.java для него, чтобы сделать из старомодного jar модуль. В качестве костыля workaround было решено просто взять и уйти распаковать все зависимости в одну кучку и сделать единый jar из которого можно попытаться сделать модный модуль-со-всеми-зависимостями. Пример на stackoverflow прилагается.

1.1.2. Потребуется включить значительно больше зависимостей, чем реально требуется


Jdeps разрешает зависимости рекурсивно, причём требует обязательного разрешения даже зависимостей, которые Maven/Gradle считают необязательными (optional). В итоге дерево зависимостей даже небольшого подопытного проекта разрастается в несколько раз. А модуль с зависимостями, который было решено изготовить в пункте (1.1.1) выкачивает пол интернета становится весьма тяжеловесным. Пример изложения сей боли здесь. Неожиданно обнаруживается, что log4j требует AWT, OSGI, ZeroMQ, Kafka или ещё что-нибудь в этом духе.

1.1.3. Неожиданный публичный [Роскомнадзор] утилиты


Обнаружилось, что в ситуации, когда некоторые классы дублируются в разных модулях, jdeps вываливается со стэктрэйсом IllegalStateException откуда-то из пучин своего кода без всякого пояснения что же пошло не так. Только одна маленькая зацепочка — сообщение «dependency on self» в качестве аргумента конструктора исключения. В какой-то момент мне показалось, что сие безобразие как бы намекало на то, что вообще всё (классы приложения, классы зависимостей, классы «необязательных» зависимостей) нужно свалить в один jar-файл. И действительно — сработало.

1.2. Проблемы с runtime


Даже когда всё уже чудесным образом собралось, модульно приложенье и даже custom образ JRE к нему, оказалось, что самые главные сюрпризы — ещё впереди. То есть в runtime.

1.2.1. Теперь невозможно определить путь стартовому файлу/каталогу


В приложения Java зачастую есть необходимость определить путь к каталогу, где сидит фазан лежит jar-файл, из которого произошёл запуск приложения (например jar-файл, содержащий точку входа). Это обычно нужно, чтобы понять, где искать файлы приложения — конфигурацию, плагины и т.п. Такие вещи, как правило лежат по соседству (что весьма логично). Для определения этого пути обычно помогает заклинание вида:

Main.getProtectionDomain().getCodeSource().getLocation().toURI()

Каково же было моё удивление, когда я обнаружил, что в новых версиях Java это заклинание более не работает и я вижу вместо пути к файлу что-то вроде «jrt://com.example.myapp». Я начал лихорадочно гуглить и переполнять стэк. Пробовал определять модуль и как-то выяснить, какие файлы к нему относятся. Попытки обращения к classpath тоже привели меня ни к чему, так как модульно приложенье запускается с так называемым module path заместо старомодного classpath. Это был финиш. Именно в этот момент я решил сворачивать свой эксперимент по переезду на Java 10. Нет, конечно можно было бы путь к каталогу передавать в командной строке или принудить пользователя запускать только из правильной директории. Но я для себя лично решил, что с меня пока что хватит.

1.2.2. Провал при попытке определения MIME-типа файла.


Оказалось, что вишенка на торте была не одна. Для экспериментов с десяткой я установил её и настроил в качестве JVM по умолчанию в системе. Поэтому сюрпризы продолжились. Код вроде

final String mimeType = Files.probeContentType(itemInputFilePath);

начал приводить к тому, что возвращался null в случае, если аргумент представлял из себя обычный CSV-файл с соответсвующим расширением. «Как же так?» — подумал я, «неужели JVM не в состоянии определить MIME-тип для обычного CSV-файла?». Я немного подебажил и обнаружил, что вызов вида

Files.readAllLines("/etc/mime.types", Charset.defaultCharset())

совершенно нагло кидает маловнятное исключение с сообщением вроде «malformed input».
Глубже в причинах этого безобразия я разбираться пока не стал. Лишь проверил файл /etc/mime.types — кракозябры не обнаружены вроде бы нормальный текстовый файл. То есть, JVM не смогла прочитать строки из текстового файла.

1.2.3. Нерабочий новый механизм Service Providers


Начиная с версии 9 Java также предлагает новый механизм Service Providers взамен старого. Вещь неплохая, позволяет делать плагины, которые разрешаются в runtime. Новый механизм подразумевает объявление расширения в module-info.java с помощью ключевых слов «provides» и «with». Казалось бы, что может быть проще. На практике это не заработало, в отличие от старого механизма (использующего файлы resources/META-INF/services/...). Разбираться, в чём проблема времени не хватило. Однако отметку о том, что без специальных заклинаний не взлетает, я пожалуй, тут сделаю.

2. Размышления о реализации local variable type inference


В случае с local variable type inference мы имеем новое ключевое слово «var» (variable, переменная), что намекает на влияние Scala. Однако лично мне показалось странным, почему не добавили также «val» (value, значение). Вместо этого приходится писать «final var», что читается глазами как «окончательная переменная» или даже как «постоянная переменная» — а это не только менее лаконично, но и как-то слегка противоречиво, на мой, привыкший к хорошему взгляд.

Также обнаружились довольно забавные вещи. Например:

final var someStrings = new ArrayList<String>();

Здесь JVM «запоминает» за именем «someStrings» тип ArrayList<String>. Иногда, при полной луне умной подсветке синтаксиса можно увидеть предупреждение, что тип константы избыточен, а в Java принято использовать в этом месте интерфейсы, например List<String> или даже Collection<String>. Этого предупреждения от шибко умного редактора можно избежать, объявив константу так: Этот тип избыточен, так как принято использовать минимально необходимый интерфейс для уменьшения потенциальной связности (чтобы никто потом не стал дёргать за ArrayList-специфичные методы, например). Local variable type inference нарушает этот принцип. Этого можно избежать следующим способом:

final var someStrings = (List<String>) new ArrayList<>();

но это уже выглядит как-то не очень лаконично. Этот момент не претендует на звание какого-то фатального недостатка, но демонстрирует лёгкий налёт противоречивости.

3. Неутешительные выводы


Некоторые из озвученных в этой записке проблем, возникли ещё в 9-й версии. Учитывая, что они так и не были пофиксеты до сих пор, есть неприятное ощущение, что весь этот бардак будет и в 11-й версии и даже далее. Не хотелось бы кликушествовать, но из этого субъективного ощущения вытекает другое: Java, как язык программирования, начинает переживать свой упадок. Возможно я не прав, а возможно так и есть и тогда на смену Java нужно искать другой инструмент.

UPDATE


К сожалению, пишу по памяти, поэтому отсутствуют некоторые детали. Вспомнил также ещё одну замечательную вещь. Это анноташка sun.misc.Contended, которая появилась в 8-й версии и была благополучно выпилена в последующих. Несмотря на свою короткую жизнь она успела попасть в одну из используемых библиотек, что также доставило немало хлопот. Нет её в 10-ке и всё, делай что хочешь, а для сборки модуля — требуется, так как ссылка на класс есть. Кончилось всё тем, что я, помня, что библиотека conversantmedia disruptor не является обязательной зависимостью, я просто заменил требуемые классы из неё пустыми в своих исходниках. И это — одна из мелочей, которым не было числа…

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


  1. sshikov
    23.04.2018 19:37

    Лично меня от попыток миграции останавливает такая простая вещь,
    как баги в maven (по большей части видел в плагинах, типа MJAR-249).

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


  1. Foror
    23.04.2018 19:49

    >Ничего просто не соберётся
    А вы чем собираете? У меня с Maven проблем не было, всё собирается, я даже ни каких module-info.java не добавлял. И в зависимостях куча древних JAR-ов. И в проекте ничего не менял, всё стандартно по мавенскому шаблону.

    >Это обычно нужно, чтобы понять, где искать файлы приложения — конфигурацию, плагины и т.п.
    У приложения должен быть константный каталог в user.home с нужной конфигурацией. Если хотите узнать о текущем процессе больше, то появился новый API ProcessHandle.

    >Files.readAllLines("/etc/mime.types", Charset.defaultCharset())
    Проверил — у меня работает.


    1. Sap_ru
      23.04.2018 20:13

      >Ничего просто не соберётся

      Это про модульные приложения. Обычные на JAR'ах и CLASSPATH'ах соберутся. Точнее, соберутся не хуже чем в 9 (там тоже понаполомали).

      У приложения должен быть константный каталог в user.home с нужной конфигурацией.

      Угу, а статические конфиги всякие, плагины, ресурсы и прочую муть? А если у меня «portable» (а у меня именно так)?
      В папке приложения теперь может быть только один файл? Простите, но это глупо. А ProcessHandle вернёт вам совершенно не то — файл может быть запущен разными способами, включая запуск из всяких «запускальщиков».

      >Files.readAllLines("/etc/mime.types", Charset.defaultCharset())
      Проверил — у меня работает.

      Проверили эту строчку или «Files.readAllLines(»/etc/mime.types", Charset.defaultCharset())"? Падает в недрах JRE.


      1. Foror
        23.04.2018 20:38

        >а статические конфиги всякие
        /etc/app.name

        >плагины
        Обычно в user.home/app.name, можно в /usr/lib/app.name Можно даже в /usr/lib/jvm

        >ресурсы и прочую муть
        Обычно пакуется в JAR

        >файл может быть запущен разными способами, включая запуск из всяких «запускальщиков»
        Если вам нужны подобные хаки, то гуглите новые хаки для 10-ки, если старые перестали работать.

        >Проверили эту строчку или
        Не нашел, чем у вас там строчка отличается. Просто скопировал, код из статьи в IDE и всё.


        1. Sap_ru
          23.04.2018 22:36

          У вас точно кросс-платформенное приложение? ;) Но фактически вы предлагаете в папке программы держать ровно один файл. Я вас уверяю, что есть множество случаев, когда нужно больше. Не говоря уже о том, что подход в любом случае спорный.
          Один JAR — снова, вы вводите искусственные ограничения.
          Простой пример — приложение под Windows взаимодействует с другими исполняемыми файлами, которые оно же устанавливает. Или приложение сильно модульное, где набор модулей задаётся на этапе установки. И ещё 1001 и одна ситуация.

          Если вам нужны подобные хаки, то гуглите новые хаки для 10-ки, если старые перестали работать.

          Хаки? Мне нужно обычное кросс-платформенное desktop GUI приложение и чтобы оно реально работало. Хаки… Тут ещё для девятки половину «хаков» не написали, а они снова поломали.


          1. Foror
            24.04.2018 07:15

            >У вас точно кросс-платформенное приложение? ;)
            Да. В Windows приложение должно лежать в Program Files/app.name. И по прежнему есть user.home

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

            >приложение под Windows взаимодействует с другими исполняемыми файлами
            >Или приложение сильно модульное, где набор модулей задаётся на этапе установки
            Для таких ситуаций делают инсталятор. И как я говорил, всё должно лежать в Program Files/app.name, в других ОС читайте инструкции, где и что должно лежать.

            >Хаки? Мне нужно обычное кросс-платформенное desktop GUI приложение и чтобы оно реально работало.
            Я вам предложил вариант. Он рабочий. Можете также использовать ProcessHandle API, если вы не наврнёте новых хаков на пускалку вашего JAR-а, то это API будет нормально работать.


    1. akurilov
      23.04.2018 21:22

      Эт вы из мира всяких инсталлятуров и скриптов к нам пришли. В моём случае пользователь просто распаковывает tgz и вперёд. Ну либо docker run, на худой конец.

      Я не могу сказать почему отломился readAllLines в моём случае. Там происходит какая-то хрень с буферами внутри и всё разлетается. И дело не в кодировке, так как файл /etc/mime.types содержит только ASCII. Просто сам факт того, что JVM v10 подавился вполне нормальным текстовым файлом, который нормально читался в 8-й JVM и кучей других программ — говорит сам за себя.


      1. Foror
        23.04.2018 21:28

        >В моём случае пользователь просто распаковывает tgz и вперёд
        И что, вы в рантайме не можете создать user.home/.app.name скопировав туда конфиги из JAR-а? И туда же устанавливать плагины, если у вас настолько простое развёртывание?

        >говорит сам за себя
        В 99.9% подобных багов это криворукость разработчика, а не сбой промышленной платформы с миллионами разработчиков.


        1. Sap_ru
          23.04.2018 22:40

          Права на папку кто будет задавать? Под Win? А если два приложения на одном компьютере?

          Промышленная платформа, как только мы говорим о десктоп приложениях — говно с огромными проблемами. Имею наглость так утверждать. Кроссплатформенности нет. Совместимость между версиями рушится раз в год. Базового функционала нет. Критические баги висят по пять лет.


          1. Foror
            24.04.2018 07:36

            >Права на папку кто будет задавать?
            Установщик или ваше приложение в рантайме.

            >А если два приложения на одном компьютере?
            Продумываете где и что хранить, когда два приложения на компьютере.

            >Кроссплатформенности нет.
            Есть, но в разумных пределах.

            >говно с огромными проблемами. Имею наглость так утверждать.
            Вас никто не держит. Только на других платформах всё еще хуже.


        1. akurilov
          23.04.2018 23:11

          >И что, вы в рантайме не можете создать user.home/.app.name скопировав туда конфиги из JAR-а? И туда же устанавливать плагины, если у вас настолько простое развёртывание?

          Можно, конечно, но это был немного не тот случай. Просто немного печально, что больше нельзя получить путь к файлу с entry point. Требуется переписывание из-за нарушения обратной совместимости, как минимум.


      1. Foror
        23.04.2018 21:58

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


        1. akurilov
          24.04.2018 10:47

          На другой машине тот же самый файл /etc/mime.types не привёл к исключению внутри JVM 10, что довольно странно

          pastebin.com/6QHQH75H


          1. Foror
            24.04.2018 11:09

            Я ниже ответил, в чём проблема.


  1. Foror
    23.04.2018 20:03

    >Java, как язык программирования, начинает переживать свой упадок
    Нет, здесь он начинает расцвет.

    >и тогда на смену Java нужно искать другой инструмент
    Т.е. искать новый инструмент и переписывать код с нуля у вас время найдётся, а почитать документацию и пофиксить недокументированные хаки баги: «Разбираться, в чём проблема времени не хватило.» ©


    1. Sap_ru
      23.04.2018 20:19

      Именно так. У меня приложение. Я за него деньги получаю. Миграция на 9 кончилась кошмаром и переписыванием массы кода. Миграция на 10 пока прошла более-менее успешно, но не без костылей.
      И я, например, отлично понимаю, когда у человека нет времени в игрушки играться. У него есть задача ему нужен инструмент, а если инструмент не работает и всё время ломается, то его нужно менять инструмент. Когда время позволяет — я копаюсь в говне. Но если у меня есть работающее, свеже-написанное приложение, а мне звонит заказчик и в панике говорит, что юзеры не могут больше скачать JRE9, то времени и желания переписывать кучу кода у меня нет — мне нужно часто и много кушать.


      1. Foror
        23.04.2018 20:44

        >то времени и желания переписывать кучу кода у меня нет
        Так сидите на 8-ке, она до 2020 поддерживается. Зачем вы ринулись под 9-ку всё переписывать? На 9-ку толком никто не переходил, только с 10-ой, когда более-менее всё отшлифовалось — люди стали переползать.

        >а если инструмент не работает и всё время ломается, то его нужно менять инструмент
        А вы думаете где-то лучше? ) Везде так, это ИТ, куча легаси и постоянное движение впёред. И джава среди прочих инструментов еще более-менее вменяемая.


        1. Sap_ru
          23.04.2018 22:44

          А ничего, что 8 не рекомендуется для новых разработок и все время предлагает перейти на более свежую версию, пугая пользователей. Более менее отшлифоваться оно должно было ещё до выхода релиза 9. А то получается, три год что уже мажорная версия сменилась, и две версии устаревшими объявлены, а оно всё еще «не отшлифовалось». Это как бы признак огромного кризиса и проблем в языке. Не говоря о том, что Вы, практически, предлагаете не писать десктоп приложения и коротко-живущие на Java, с чего мы и начали.


          1. Foror
            24.04.2018 07:31

            >8 не рекомендуется для новых разработок
            Всё верно, зачем новую разработку начинать на устаревшей платформе? Кто так делает?

            >все время предлагает перейти на более свежую версию
            Не видел такого, т.е. у пользователя на Windows стоит 8-ка и Updater постоянно предлагает обновиться на 10-ку?

            >Это как бы признак огромного кризиса и проблем в языке.
            Нет, это перемены, необходимые для дальнейшего роста популярности JVM. Сделали, то, что давно нужно было сделать. Такие точки перелома есть везде, например Windows 98 -> Windows XP или x32 -> x64 и т.д.


    1. akurilov
      23.04.2018 21:23

      Я имел ввиду — в долгосрочной перспективе. Не связываться с новыми проектами на Java, например. Ну это если я прав, а я ещё не уверен. Может всё починят всё-таки.


  1. eliduvid
    23.04.2018 21:25

    Про malformed input у меня было в восьмёрке ещё. Это несовпадение кодировками. У меня было когда читал в utf8 (стандартная кодировка), а в файле был иврит в какой-то ещё (iso что-то, windows что-то — не помню).


    1. akurilov
      23.04.2018 21:26

      В файле вроде только ASCII. К тому же вызов изнутри явы я никак поменять не могу.


      1. Sap_ru
        23.04.2018 22:46

        Локали там поломаны у вас. Причём, обещали именно в 10 всё сделать круто ASCII.


      1. Foror
        24.04.2018 09:00

        >К тому же вызов изнутри явы я никак поменять не могу
        Можете создать свой FileTypeDetector через ServiceLoader он подгрузится и выполнится первым. То что в файле ASCII это без разницы. Там нет детектора кодировки файла, поэтому берётся Charset.defaultCharset(), вы сами это указали в статье. И видимо у вас там какой-нибудь UTF-16 возвращается и он начинает читать однобайтовую кодировку, как двухбайтовую.


        1. Foror
          24.04.2018 09:13

          Хотя сейчас глянул код defaultCharset, lookup(csn) просто выкидывает эксепшен, если у вас file.encoding == null. И там же рядом выставляет UTF-8, если не удалось детектировать кодировку по значению file.encoding, что с первого взгляда глупо (можно было бы тогда и в первом случае делать кодировку UTF-8):

                          String csn = GetPropertyAction
                                  .privilegedGetProperty("file.encoding");
                          Charset cs = lookup(csn);
                          if (cs != null)
                              defaultCharset = cs;
                          else
                              defaultCharset = sun.nio.cs.UTF_8.INSTANCE;
          


        1. akurilov
          24.04.2018 09:55

          В конечном итоге всё равно проверяется по расширению. Поэтому проще было не дёргать probeContentType а проверять расширение самому. Но использование кастомного FileTypeDetector — это слишком


          1. Foror
            24.04.2018 11:12

            Да проблема просто решается, проверяйте system properties на наличие file.encoding и если оно в null, то выставляйте в UTF-8. И тогда defaultCharset отработает без исключений и откроет mime.type файл. Можете в OpenJDK багтрекер сообщить об этой проблеме, если еще никто не сообщал.


            1. akurilov Автор
              24.04.2018 15:56

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


              1. akurilov Автор
                25.04.2018 08:48

                Воспроизвёл. Код:

                import java.nio.file.Files;
                import java.nio.file.Paths;
                import java.nio.charset.Charset;
                
                public final class Test {
                        public final static void main(final String args[])
                        throws Exception {
                                Files.readAllLines(Paths.get("/etc/mime.types"), Charset.defaultCharset());
                        }
                }
                


                Стэктрэйс:
                $ java Test 
                Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
                Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1
                        at java.nio.charset.CoderResult.throwException(CoderResult.java:281)
                        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
                        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
                        at java.io.InputStreamReader.read(InputStreamReader.java:184)
                        at java.io.BufferedReader.fill(BufferedReader.java:161)
                        at java.io.BufferedReader.readLine(BufferedReader.java:324)
                        at java.io.BufferedReader.readLine(BufferedReader.java:389)
                        at java.nio.file.Files.readAllLines(Files.java:3205)
                        at Test.main(Test.java:8)
                [kurila@ruxxkurilad2c tmp]$ java -version
                Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
                openjdk version "1.8.0_162"
                OpenJDK Runtime Environment (build 1.8.0_162-b12)
                OpenJDK 64-Bit Server VM (build 25.162-b12, mixed mode)
                


            1. akurilov Автор
              24.04.2018 16:03

              В классе sun.nio.cs.CharsetDecoder есть метод decode, в котором есть участок:

                          if (cr.isUnderflow()) {
                              if (endOfInput && in.hasRemaining()) {
                                  cr = CoderResult.malformedForLength(in.remaining());
                                  // Fall through to malformed-input case
                              } else {
                                  return cr;
                              }
                          }
              


  1. kalininmr
    23.04.2018 23:01

    final var someStrings = (List<String>) new ArrayList<>();


    да уж. за что боролись. както совсем подурацки выглядит.
    хотя конечно можно понять причины.
    но хотелось тыгда уж чтото вроде
    List<String> someStrings = new ArrayList<>();


  1. YuryB
    23.04.2018 23:29

    «Размышления о реализации local variable type inference»
    а джава как должна узнать какой супер интерфейс из множества делать var'у?
    ну и вам очевидно «подсвечивает» не джава а IDE, так что решение этой проблемы на их плечах и в чём тут «джаву» обвинять я не понимаю.

    Ну и в целом какие-то глобальные выводы делаете от обиды, что само сразу работать не стало :)
    ЗЫ: «Провал при попытке определения MIME-типа файла.» это тоже мега проблемой не выглядит и на мой взгляд джуну по силу разобраться в чём дело.


    1. akurilov
      23.04.2018 23:34

      а джава как должна узнать какой супер интерфейс из множества делать var'у?

      а почему нет? минимально возможный, на основе статического анализа кода. не?

      ну и вам очевидно «подсвечивает» не джава а IDE, так что решение этой проблемы на их плечах и в чём тут «джаву» обвинять я не понимаю.

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

      Ну и в целом какие-то глобальные выводы делаете от обиды, что само сразу работать не стало :)
      Не совсем. Я ждал что в 10-ке проблем с модулями уже не будет, но осталось множество вещей, которые делают модули совершенно неюзабельными. Не стало работать ни сразу, ни потом. Для полноты картины — вот, например, удачная цитата:
      Wow… this makes jlink from hard to use to useless for the foreseeable future. – pupeno Apr 7 at 9:36

      взято отсюда
      stackoverflow.com/questions/48408454/java-9-generating-a-runtime-image-with-jlink-using-3rd-party-jars
      ЗЫ: «Провал при попытке определения MIME-типа файла.» это тоже мега проблемой не выглядит и на мой взгляд джуну по силу разобраться в чём дело.
      У меня нету столько джунов, чтобы бросить их на решение этих 1000 и 1 мелочей. Самому — лень, естественно. Не барское это дело. Я как-то, когда берусь за задачу, обычно выставляю себе лимит времени.


      1. Optik
        24.04.2018 11:56

        минимально возможный
        Как определен «минимальный»?

        ну если IDE догадывается, то и компилятор тоже вполне мог бы
        Зачем вообще в типе подменять на интерфейс?


        1. akurilov Автор
          24.04.2018 15:44

          Вроде как так принято — использовать минимально необходимый интерфейс в качестве типа. Для уменьшения потенциальной связности. Local variable type inference нарушает этот принцип.


          1. akurilov Автор
            24.04.2018 15:52

            Добавил сие пояснение в статью


          1. Optik
            25.04.2018 11:14

            Т.е. авторитет разработчиков языка не остановил вас от разбирательства в деталях, а авторитет человека неизвестного останавливает.

            Я предлагаю вам задуматься над этим «так принято» и переосмыслить критически. Посмотреть в каких случаях что куда приводит, в том числе с учетом вариативности, в том числе с учетом лямбд.

            Пока что выглядит как призыв к анемичности (если я корректно интерпретировал «минимальность»).


            1. akurilov Автор
              25.04.2018 11:40

              Я изначально неправильно выразился. «Анемичность» нужна для уменьшения потенциальной связности.


  1. vlanko
    24.04.2018 12:58

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


  1. JackFrostDeCuba
    24.04.2018 15:43

    Кстати, почему куча софта требует Яву 8? Как быстро разработчики перепрыгнут на 9->10?


    1. akurilov Автор
      24.04.2018 15:54

      Переход на 9 или 10 обещает пока что много боли, так как многие используемые библиотеки собраны под 8-ку и просто не будут работать. Особенно, если вы захотите использовать модули (простого решения проблем с библиотеками пока не наблюдается).


  1. echipachenko
    24.04.2018 15:44

    Тут возникло много споров по поводу того, нормально собирается или нет.
    Так вот.
    Hello-world проект на Spring Boot скачан со спрингового же репозитория с Java 9 не работает.
    На 8-й всё шикарно. =)
    Чую скоро будет боль. Много боли.


    1. JackFrostDeCuba
      24.04.2018 16:16

      Какая чудесная обратная совместимость.


      1. apangin
        24.04.2018 17:08

        Что уж говорить, если даже стандартный пример Java2Demo, скачанный с официального сайта Oracle из раздела JDK 8u172 Demos and Samples, просто не запускается на JDK 10.