Ссылка для скачивания
Последнюю половину года мы подробно обсуждали здесь новшества 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.
Долгий путь к релизу
На самом деле, нет. Это самый быстрый полноценный релиз в истории!
Раньше план публиковался на странице проекта, но больше он нам не понадобится. Все этапы успешно выполнены.
- 2017/12/14 Первая фаза замедления
- 2018/01/11 All Tests Run
- 2018/01/18 Вторая фаза замедления
- 2018/02/08 Первый Release Candidate
- 2018/02/22 Окончательный Release Candidate
- 2018/03/20 General Availability
И что, всё хорошо?
В основном, да. В этом релизе разработчики фокусировались на починке только тех багов, которые являются совершенно критичными для успеха Java 10. Все задачи, относящиеся к другим релизам Java, даже с высшим приоритетом, отложены.
Но какой же релиз без хорошего факапа? Тагир Валеев (lany) через считаные часы опубликовал в своём твиттере новость об эпическом новом баге в компиляторе.
Баг уже обсуждают в рассылке и ведётся работа по его починке.
Вот этот код, можно вставить и проверить:
public class Main {
void m() {
var s = java.util.List.of("a", 1);
}
}
Проблема проявляется только только при включённом флаге -g
, который говорит о необходимости генерации отладочной информации. В IDE он включён по-умолчанию, так что мимо ошибки не пройти :-)
Изменения, которые появились в этом релизе
JEP 286: Local-Variable Type Inference.
Локальный вывод типов с помощью var
. Неоднозначная фича. Регулярно вызывает бурления в рассылке.
Пример кода:
var list = new ArrayList<String>(); // infers ArrayList<String>
var stream = list.stream(); // infers Stream<String>
Бородатый анекдот в тему.
Заходит джавист в столовую и говорит: дайте, пожалуйста, Борщ борщ нью Борщ!
JEP 296: Консолидация леса исходников JDK в едином репозитории.
Широкой общественности обычно не интересно, разве что ты собираешь OpenJDK из исходников. Интересней то, что чем меньше хаоса в проекте, тем более качественный получается продукт.
JEP 304: Garbage-Collector Interface.
Улучшение изоляции основных исходников от GC путём создания хорошего чистого интерфейса для GC. В последнее время стало весьма популярным писать свои GC: на подходе у нас Shenandoah, ZGC, Epsilon. Чтобы поддержать эти благие начинания, разработчикам OpenJDK пришлось конкретно разгрести свалку в коде, чтобы не только максимально упроситить создание новых GC, но и дать возможность быстро отключать ненужные GC из сборки. Один из основных критериев успеха — отсутствие просадки по перфомансу после всех этих рефакторингов.
JEP 307: Parallel 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 312: Thread-Local Handshakes.
Возможность выполнять колбэк на тредах, не делая глобальный для JVM сейфпоинт. Фича позволяет дешёво останавливать одиночные треды, а не только «всё или ничего». Это низкоуровневая системная фича, вручную ей воспользоваться нельзя, но можно радоваться автомагически возросшей производительности программ.
JEP 313: Remove the Native-Header Generation Tool.
Утилита javah
больше не нужна, потому что нативные заголовки теперь может делать javac (начиная с JDK8, на самом деле).
javah
была утилитой, генерирующей сишные заголовочные файлы и исходники, необходимые для использования нативных методов. Сгенерированные ей файлы предназначены для использования в программах, написанных на Си, чтобы обращаться к экземплярам джавовых объектов из неуправляемого нативного кода. В .h-файле определяется структура, которая выглядит примерно как класс, которым мы собираемся управлять. Поля структуры — переменные экземпляра класса. Тем не мнее, в JNI использование подобных стабов не является обязательным.
JEP 314: Additional Unicode Language-Tag Extensions.
Поддержка новых расширений Unicode: cu (currency type), fw (first day of week), rg (region override), tz (time zone).
JEP 316: Heap Allocation on Alternative Memory Devices.
HotSpot VM теперь может выделять хиповую память на других девайсах, например, на NV-DIMM. Некоторые операционки уже умеют выделять не-DRAM память, помещая её на файловую систему, например, NTFS DAX и ext4 DAX. Добавляется опция ` -XX:AllocateHeapAt=.
JEP 317: Experimental 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 319: Root Certificates.
В JDK имеется кейстор cacerts
, который нужен для хранения корневых сертификатов. Но в OpenJDK он пока пустой. Поэтому ништяки типа TLS в OpenJDK по-умолчанию не работают. Теперь этот cacerts
будет правильно сконфигурирован и заполнен, и ништяки начнут работать. Кроме того, это сгладит разницу между OpenJDK и Oracle JDK.
JEP 322: Time-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)
Nagg
21.03.2018 14:53+8Заходит джавист в столовую и говорит: дайте, пожалуйста, вар борщ нью Борщ!
xlenz
21.03.2018 23:42А я рад, что наконец-то будет var вместо LinkedHashMap <String, HashMap <String, Object>> и подобного.
Наличие вар не запрещает указывать типы там, где это нужно...
Многословие джавы отталкивает людей, есть что улучшать, никого не обидев, сохраняя баланс
st0ke
22.03.2018 09:05+4На code-review, когда используется такой вывод типов, постоянно возникает вопрос, а подумал ли автор о типе переменной, он (тип) действительно не важен или человеку было просто лень и он «фигачил» строки одна за одной? Не знаю как в Java, а в C++ это довольно важный аспект при написании кода.
Плюсом ещё и изобретается аналог венгерской нотации (если совсем прищуриться), когда в название переменной засовывается информация о типе (в большей мере, чем нужно).
Нисколько не отрицаю мнения, что монстрообразные название типов действительно можно упрощать до автоматического вывода, но писать везде поголовно это опасно и нечитаемо (читаемо конечно, но времени больше тратится). В тех же плюсовых шаблонах иногда действительно лучше написать auto, а не пытаться понять, что там в итоге то должно быть.
Многие ещё говорят, что IDE же выводит тип, только вот у вас когда определенно 10 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где, а через какое-то время повторять эту процедуру.
Жаль, что строгость кода почему-то не находит понимание.kalininmr
22.03.2018 11:05+1почему тип неважен?
скорее следует понимать, что var делает такой же тип как с права.
что и нужно в 99% процентах случаев создания объекта, где это и напрягает тавтологией.st0ke
22.03.2018 12:20+2почему тип неважен?
В случае, когда auto x = new Something, да, тавтология уходит, тут имелся в виду случай auto users = smth.getUsers()st0ke
22.03.2018 12:31+1А дальше например идет foreach по этому контейнеры (то что это контейнер ясно из название функции и переменной, однако тут же вопрос, а вдруг там не линейный контейнер, а какой-то более сложный тип?)
Free_ze
22.03.2018 13:06+1однако тут же вопрос, а вдруг там не линейный контейнер, а какой-то более сложный тип?
Названия функции-фабрики и принимающей переменной не подразумевают никакой специфики.
olegchir Автор
22.03.2018 11:07Я обычно пишу выражение, потом нажимаю ctrl+alt+V в Идее, запускается рефакторинг Extract Variable, и остаётся только вписать название новой переменной. То есть по сути, происходит то же самое что и с var, но убого.
Free_ze
22.03.2018 12:12+110 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где
auto
иvar
— все-таки разные вещи, хотя и юзкейсы похожи. Характерно то, что у Майерса про вывод типов отдельная глава в книжке, а проvar
редко где больше одного абзаца пишут.
Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?
Жаль, что строгость кода почему-то не находит понимание.
Строгости кода это не мешает, зато DRY поддерживает.olegchir Автор
22.03.2018 12:22Зачем типы запоминать, есть же IDE. Можно или навести мышкой с зажатым ctrl, или если не используешь мышку — нажать ctrl+Q когда переменная под курсором
Free_ze
22.03.2018 12:32+5Мышкой водить по всем переменным — тоже не самое продуктивное решение и не факт, что с тем же
auto
подсказка будет полезной. Да и всякие диффы смотреть в разных приложениях, которые не умеют анализировать типы в контексте проекта, будет не так удобно.
Кмк, автовывод полезен там, где тип очевиден, а этого нужно добиваться другими средствами: именем самой переменной, именем той фабрики, откуда значение берется и сколь возможно малым расстоянием между инициализацией и использованием. Если есть сомнение, то лучше лишний раз написать его полностью.olegchir Автор
22.03.2018 16:26Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы. В частности, названия типов не должно быть частью имени метода.
Олсо, это очень удобно, когда у тебя какой-нибудь чудовищный тип, например, лист мапов мапов мапов из листов в листы. И ты этот тип не хочешь видеть глазами, потому что он напрягает.
Free_ze
22.03.2018 17:23+1Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы.
Я бы посмотрел на такой API, где в названиях намеренно избегают любых отсылок к типам) Шутка, я бы не хотел такого видеть никогда.
Если серьезно, тут уже был примерчик насчет методаgetUsers()
. Вам что-либо говорит это название о том, что из него можно получить?olegchir Автор
22.03.2018 20:26+1Что угодно оно может вернуть.
List
,Set
,Array
, и дажеQueue
!
Дальше результат, скорей всего, будет итерироваться через короткую форму записи for loop. При этом знать, какой там конкретный формат хранения — не нужно, for сработает со всеми!
Тут можно бы спросить: а что, если getUsers() вернёт
HashMap
? Фокус не сработает?
Конечно сработает, потому что IDE-то знает о настоящем типе!
Как происходит итерирование в IntelliJ IDEA? Ты пишешь слово
iter
и нажимаешь[TAB]
. Вылезает вот такая подсказка:
Которая после применения ведёт, например, к такой замене:
При этом, если там изначально была не мапа, а список, то варианты будут другие:
Работает ли это с
var
? Да, работает.
Работает ли это с
var
, который получает данные снаружи? Работает.
Такие дела.
Не нужно вводить сущности, которые не нужны. Не сломается то, чего нет.
В данном случае нам не нужно знать способ хранения юзеров.
Free_ze
22.03.2018 20:52Что угодно оно может вернуть. List, Set, Array, и даже Queue!
Именно! Здесь будет некаяCollection<User>
. Не указав тип явным образом мы создали у программиста-юзера необходимую ассоциацию в терминах предметной области.
Тут можно бы спросить: а что, если getUsers() вернёт HashMap? Фокус не сработает?
Конечно нет. А какого вида хэшмап от юзеров вы себе представляете? Словарь, как правило, отражает какое-то отношение (ключ-значение, которые вряд ли будут относиться к единой сущности), а никак не множества (в математическом смысле) значений. Тогда и названия будут иными.
st0ke
22.03.2018 12:36+1Вывод типа то есть, но это в любом случае надо позиционировать курсор на переменной и нажимать клавиши. Если таких переменных много, то вызывает больше неудобств, чем сложностей у человека указать явно тип, когда он писал код.
st0ke
22.03.2018 12:30+2auto и var — все-таки разные вещи, хотя и юзкейсы похожи.
Прошу меня извинить за непонимаю, что там придумали в Java, но кажется auto просто более фунциональней, потому что можно писать, например auto * или const auto &. А так же ещё auto можно засовывать в тип аргумента функции (шаблоны для бендых) и результирующее значение. Или же я изначально не прав?
Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?
Запомнить в прямом смысле). Загрузить в свой мозг объект, у которого тип такой-то и согласно типу, скорее всего можно провести вот такие-то операции, такие-то операции делать оптимально (с точки зрения быстродействия), такие-то нет. Если код сложный, то спрятанный тип загружает мозг сильней, чем если бы человек не поленился и написал тип.
Строгости кода это не мешает, зато DRY поддерживает.
Вам тоже отмечу, что против конструкции auto x = new Something ничего против не имею. Проблема возникает, когда зовут функцию, например process, в которой название отвечает за действие, а не за тип возвращаемого значения.
auto r = process();
Что такое r? Какой-то результат. Не везде есть возможность и тип результата и действие уместить в одно название и неПолучитьОченьДлинноеНазваниеФункцииКотораяДелаетААвозващаетБFree_ze
22.03.2018 13:00+1auto просто более фунциональней
В том и дело, результат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 )
и однобуквенное название заставляет идти туда, где оно инициализировано. Да, возможно это чем-то похоже на венгерскую нотацию, но оно более семантично, т.к. привязывается не к типу имплементации, а к значению в контексте конкретного юзкейса.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 по всем исходникам.Free_ze
22.03.2018 14:08+1усложняет чтение кода
Все зависит от кейса. Вы же согласились насчетБорщ борщ = new Борщ();
? Так вот и я категорически против распихивания вывода типов везде, где скомпилируется.
со временем отупляет
И волосы на руках начинают расти!) Про автокомплит когда-то то же самое говорили.
auto/var вывело int32, а мы потом умножили его несколько раз или вычли из unsigned и ушли за ноль
Вы пишите выражение с каким-то параметром, если не подумали про переполнение типа, то явное его декларирование не спасет.
а если везде указан тип, то достаточно бы было сделать grep по всем исходникам.
Аргумент, вместо прямого поиска вам придется найти фабрику и грепать по ней. Хотя, это настолько же усложняет рефакторинг типа возврата.
olegchir Автор
22.03.2018 16:28со временем отупляет
тогда функциональное программирование — это вообще ад и содомия, мозгов не остаётся совсем!
PastorGL
21.03.2018 22:59Не-а, не будем мы мигрировать. Мы по старой энтерпрайзной привычке подождём LTS. Тем более, что до него недолго совсем осталось.
JediPhilosopher
21.03.2018 23:01Блин, что делается, куда мир летит, мы еще на 8 джаву не перешли толком (а кое-где еще и с 6 не слезли, и даже 7 еще кажется какой-то опасной новой диковиной на которую никак перекатить кучи легаси проектов не могут), а тут уже 10 выходит. Куда вообще 9 делась, я ее даже заметить не успел! Ааа, остановитесь, подождите, я не успеваю.
jbaruch
22.03.2018 02:21для вас, дорогие
слоупокиэнтерпрайзиники, придумали LTS версии. Остальные можно спокойно игнорировать.
relgames
22.03.2018 00:41Ну и как обычно, для многих библиотек выход новой Java — полная неожиданность.
К примеру, Lombok не работает.lany
22.03.2018 05:33Так нечего было им пользоваться :-) Понятно, что такие шибко хакерские вещи, которые прямо скажем ломают джаву изнутри, сами очень хрупкие.
olegchir Автор
22.03.2018 05:47А почему они его не проапдейтили до десятки?
lany
22.03.2018 07:25+2На самом деле проапдейтили, даже в CHANGELOG написали, только поленились выпустить свежую версию почему-то. А вообще ты донат занёс людям или только требовать умеешь? ;-)
olegchir Автор
22.03.2018 07:57> А вообще ты донат занёс людям или только требовать умеешь? ;-)
Я умею не использовать у себя Lombok! :-)
Alt+Enter, Getter and Setter, Enter, Enter, как-то так. А ещё можно расчехлить JavaParser и переехать им исходники в цикле, если совсем ленивый.lany
22.03.2018 07:58+2Блин, а я публичные поля оставляю просто.
olegchir Автор
22.03.2018 08:39+3А я делаю геттеры-сеттеры, потому что в течение N лет старшие товарищи били по рукам, когда пытался делать публичные поля.
Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…Skerrigan
22.03.2018 09:18+1Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…
Не вы один… /смотрит с укором на половину своего кода, построенного по принципу карго-культа, вздыхает с мыслью «ну зато работает збс»...
relgames
22.03.2018 09:47+1Объекты надо любить! Раз в год бывает нужда таки расширить геттер или сеттер и вставить проверку, например.
Насколько это оправдывает геттеры/сеттеры — хз.
olegchir Автор
22.03.2018 10:26У меня в вебе все проверки в отдельных классах-валидаторах)
relgames
22.03.2018 10:31+1Это же не тру ООП!
Ну ещё ломбок генерит конструкторы, и это круто работает с новым Спрингом — можно писать private final поля, Ломбок сгенерит конструктор и спринг через конструктор вставит бины.
AstarothAst
22.03.2018 10:55+1Это же не тру ООП!
Почему? Наоборот, SOLID во все поля! Под задачу валидации выделен отдельный класс, который несет только одну ответственность :D
lany
22.03.2018 11:48+2И валидацию параметров конструктора ломбок прикрутит? Если у меня
class Range { private final int from, to; }
и инвариантfrom <= to
, куда мне инвариант впихнуть?relgames
22.03.2018 11:55+1В этом случае мы пишем конструктор.
Ломбок — молоток, шурупы им не закручиваем.
Если в проекте гвоздей нет — то Ломбок и не нужен. Нам лично, в нашем проекте — он помогает.
dernasherbrezon
22.03.2018 12:26+1У меня в коде иногда бывает сначала:
public long getTotal() { return this.number1 + this.number2; }
А потом выясняется что нужно хранить в базе и тогда получается:
public long getTotal() { return this.total; }
Геттеры/Сеттеры все таки полезны. Тем более они генерируются IDE по одной кнопке.
TheKnight
22.03.2018 12:45+1Сделать правильный геттер или сеттер в случае с ломбоком не сложно. Достаточно его просто написать.
А в связанном коде оно и так все через геттеры и сеттеры работает.
AstarothAst
22.03.2018 10:24+1Можно я буду ссылаться на этот коммент, когда мне в следующий раз скажут, что публичные поля — это не по феншую?
lany
22.03.2018 11:46+1Можно! Главное — головой думать, когда программируешь, а не фэншуем заниматься.
relgames
22.03.2018 09:49+1Мы начали его использовать, когда поля постоянно менялись, была такая дикая фаза. Сейчас поспокойней, но Lombok как-то прижился.
relgames
22.03.2018 10:01+1Да ладно. И ещё кучей вещей не пользоваться. Сидеть на голой джаве.
Есть подозрение, что сломан не только Lombok. Просто он самый первый в цепочке компиляция-запуск. И дальше я пока не прошел, проще подождать немного, пока пофиксят.
В прошлый раз, уже после выхода 9, были проблемы у jooq. Logstash вроде бы до сих пор на 9 не запускается.
Блин, похоже, удел ынтырпрайза — LTS :(
olegchir Автор
22.03.2018 10:28То есть LTS — это удел ынтерпрайза, а вот юзать сырую, никем кроме трех человек не поддерижваемую штуку Lombok — это конечно ого-го удел :)
relgames
22.03.2018 10:33+1Так я же 10 для себя попробовал :)
На личном проекте, где 9 работает.
Но там Ломбок больше по привычке.
На работе — 8, там Ломбок работает отлично.
dougrinch
22.03.2018 05:25Утилита javah больше не нужна, потому что нативные заголовки теперь может делать javac
Очень интересно. Я правильно понимаю, что если у меня сорцы на котлине, то теперь хрен мне, а не jni? Спасибо тебе, Оракл, что заставляешь в полностью котлиновском проекте заводить единственный джавовый класс со всеми нативными методами.olegchir Автор
22.03.2018 05:55+1Разве Котин генерит что-то специфичное для десятой жабы? А как придёт время, в JB что-нибудь придумают, наверняка у них самих external'ов дофига
Можно попробовать выделить external методы в отдельные классы, собирать их с jvmTarget=1.8, и потом натравливать на них javac из старых версий JDKdougrinch
22.03.2018 10:19+2Так javac же принимает на вход сорцы! И именно поэтому я не могу натравить его на котлин. В отличии от javah, которому нужны .class.
lany
Если я правильно помню, там был более хитрый алгоритм: надо просто написать
var x = "foo"
, а когда подсветит красным, там есть квик-фикс на нём. Так-то в 2017.3 у нас уже всё работало. Но вообще да, проще на 2018.1 уже перейти.olegchir Автор
Sultansoy
А можно вашу цветовую схему узнать?
olegchir Автор
Это очень крутой плагин под названием Material Theme UI (точнее, Material Theme UI EAP по понятной причине). Оно меняет все картинки и цвета в UI. Это одна из стандартных схем, идущих с ним в коробке: Material Palenight. Там ещё несколько клёвых схем в комплекте есть!
Очень рекомендую. Я бы на месте JB вообще поставил бы этот плагин по умолчанию, уж слишком всё няшное стаёт.
tundrawolf_kiba
Этот кстати сейчас обновляется гораздо активнее, а EAP разработчик кажется забросил полгода назад.
olegchir Автор
Ох ничоси. Обновлюсь-ка на него.
AstarothAst
Что-то он на смену размера шрифта не реагирует…
olegchir Автор
А где меняешь? Editor -> Color Scheme -> поставить галку «Use color scheme font instead of default», выставить значение Size
AstarothAst
Да, уже нашел, спасибо!
пока непривычно как-то :) Но няфффно, это да :D