Comments 84
потому что на стабильной 2017.3.5 не поддерживается этот language level.
Если я правильно помню, там был более хитрый алгоритм: надо просто написать var x = "foo"
, а когда подсветит красным, там есть квик-фикс на нём. Так-то в 2017.3 у нас уже всё работало. Но вообще да, проще на 2018.1 уже перейти.
Это очень крутой плагин под названием Material Theme UI (точнее, Material Theme UI EAP по понятной причине). Оно меняет все картинки и цвета в UI. Это одна из стандартных схем, идущих с ним в коробке: Material Palenight. Там ещё несколько клёвых схем в комплекте есть!
Очень рекомендую. Я бы на месте JB вообще поставил бы этот плагин по умолчанию, уж слишком всё няшное стаёт.
Material Theme UI
Этот кстати сейчас обновляется гораздо активнее, а EAP разработчик кажется забросил полгода назад.
… Эпический баг компилятора
Вы точно уверены? ))
Заходит джавист в столовую и говорит: дайте, пожалуйста, вар борщ нью Борщ!
— Суп!
— Борщ, Гороховый, Солянку?
— NoUniqueBeanDefinitionException…
Плюсом ещё и изобретается аналог венгерской нотации (если совсем прищуриться), когда в название переменной засовывается информация о типе (в большей мере, чем нужно).
Нисколько не отрицаю мнения, что монстрообразные название типов действительно можно упрощать до автоматического вывода, но писать везде поголовно это опасно и нечитаемо (читаемо конечно, но времени больше тратится). В тех же плюсовых шаблонах иногда действительно лучше написать auto, а не пытаться понять, что там в итоге то должно быть.
Многие ещё говорят, что IDE же выводит тип, только вот у вас когда определенно 10 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где, а через какое-то время повторять эту процедуру.
Жаль, что строгость кода почему-то не находит понимание.
скорее следует понимать, что var делает такой же тип как с права.
что и нужно в 99% процентах случаев создания объекта, где это и напрягает тавтологией.
почему тип неважен?
В случае, когда auto x = new Something, да, тавтология уходит, тут имелся в виду случай auto users = smth.getUsers()
однако тут же вопрос, а вдруг там не линейный контейнер, а какой-то более сложный тип?
Названия функции-фабрики и принимающей переменной не подразумевают никакой специфики.
а тавтология резко снижает читабельность
имя типа контейнера запросто может выйти 50+ символов — повторять както нечитабельно.
10 переменных и у всех auto, это все равно мука узнавать и запоминать, какой тип где
auto
и var
— все-таки разные вещи, хотя и юзкейсы похожи. Характерно то, что у Майерса про вывод типов отдельная глава в книжке, а про var
редко где больше одного абзаца пишут.Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?
Жаль, что строгость кода почему-то не находит понимание.
Строгости кода это не мешает, зато DRY поддерживает.
auto
подсказка будет полезной. Да и всякие диффы смотреть в разных приложениях, которые не умеют анализировать типы в контексте проекта, будет не так удобно.Кмк, автовывод полезен там, где тип очевиден, а этого нужно добиваться другими средствами: именем самой переменной, именем той фабрики, откуда значение берется и сколь возможно малым расстоянием между инициализацией и использованием. Если есть сомнение, то лучше лишний раз написать его полностью.
Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы. В частности, названия типов не должно быть частью имени метода.
Олсо, это очень удобно, когда у тебя какой-нибудь чудовищный тип, например, лист мапов мапов мапов из листов в листы. И ты этот тип не хочешь видеть глазами, потому что он напрягает.
Я постараюсь дизайнить API так, чтобы было совершенно всё равно, какие там типы.Я бы посмотрел на такой API, где в названиях намеренно избегают любых отсылок к типам) Шутка, я бы не хотел такого видеть никогда.
Если серьезно, тут уже был примерчик насчет метода
getUsers()
. Вам что-либо говорит это название о том, что из него можно получить?Что угодно оно может вернуть. List
, Set
, Array
, и даже Queue
!
Дальше результат, скорей всего, будет итерироваться через короткую форму записи for loop. При этом знать, какой там конкретный формат хранения — не нужно, for сработает со всеми!
Тут можно бы спросить: а что, если getUsers() вернёт HashMap
? Фокус не сработает?
Конечно сработает, потому что IDE-то знает о настоящем типе!
Как происходит итерирование в IntelliJ IDEA? Ты пишешь слово iter
и нажимаешь [TAB]
. Вылезает вот такая подсказка:
Которая после применения ведёт, например, к такой замене:
При этом, если там изначально была не мапа, а список, то варианты будут другие:
Работает ли это с var
? Да, работает.
Работает ли это с var
, который получает данные снаружи? Работает.
Такие дела.
Не нужно вводить сущности, которые не нужны. Не сломается то, чего нет.
В данном случае нам не нужно знать способ хранения юзеров.
Что угодно оно может вернуть. List, Set, Array, и даже Queue!Именно! Здесь будет некая
Collection<User>
. Не указав тип явным образом мы создали у программиста-юзера необходимую ассоциацию в терминах предметной области.Тут можно бы спросить: а что, если getUsers() вернёт HashMap? Фокус не сработает?Конечно нет. А какого вида хэшмап от юзеров вы себе представляете? Словарь, как правило, отражает какое-то отношение (ключ-значение, которые вряд ли будут относиться к единой сущности), а никак не множества (в математическом смысле) значений. Тогда и названия будут иными.
когда у тебя какой-нибудь чудовищный тип, например, лист мапов мапов мапов из листов в листы. И ты этот тип не хочешь видеть глазами, потому что он напрягает.
Вот я такой тип не столько видеть не хочу, сколько работать с ним. Потому что видеть я его может и перестану, а думать о нем придется — где в этой каше что, и как именно извлекается. По-моему такого психоза лучше избегать всеми силами, и var тут только маскирует проблему, а не решает ее.
auto и var — все-таки разные вещи, хотя и юзкейсы похожи.
Прошу меня извинить за непонимаю, что там придумали в Java, но кажется auto просто более фунциональней, потому что можно писать, например auto * или const auto &. А так же ещё auto можно засовывать в тип аргумента функции (шаблоны для бендых) и результирующее значение. Или же я изначально не прав?
Но что значит «запоминать тип»? Он неоднозначен или контекст теряется настолько, что даже имя не может помочь определиться?
Запомнить в прямом смысле). Загрузить в свой мозг объект, у которого тип такой-то и согласно типу, скорее всего можно провести вот такие-то операции, такие-то операции делать оптимально (с точки зрения быстродействия), такие-то нет. Если код сложный, то спрятанный тип загружает мозг сильней, чем если бы человек не поленился и написал тип.
Строгости кода это не мешает, зато DRY поддерживает.
Вам тоже отмечу, что против конструкции auto x = new Something ничего против не имею. Проблема возникает, когда зовут функцию, например process, в которой название отвечает за действие, а не за тип возвращаемого значения.
auto r = process();
Что такое r? Какой-то результат. Не везде есть возможность и тип результата и действие уместить в одно название и неПолучитьОченьДлинноеНазваниеФункцииКотораяДелаетААвозващаетБ
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 )
и однобуквенное название заставляет идти туда, где оно инициализировано. Да, возможно это чем-то похоже на венгерскую нотацию, но оно более семантично, т.к. привязывается не к типу имплементации, а к значению в контексте конкретного юзкейса.
Что это за результат по имени «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 по всем исходникам.
усложняет чтение кодаВсе зависит от кейса. Вы же согласились насчет
Борщ борщ = new Борщ();
? Так вот и я категорически против распихивания вывода типов везде, где скомпилируется.со временем отупляетИ волосы на руках начинают расти!) Про автокомплит когда-то то же самое говорили.
auto/var вывело int32, а мы потом умножили его несколько раз или вычли из unsigned и ушли за нольВы пишите выражение с каким-то параметром, если не подумали про переполнение типа, то явное его декларирование не спасет.
а если везде указан тип, то достаточно бы было сделать grep по всем исходникам.Аргумент, вместо прямого поиска вам придется найти фабрику и грепать по ней. Хотя, это настолько же усложняет рефакторинг типа возврата.
со временем отупляет
тогда функциональное программирование — это вообще ад и содомия, мозгов не остаётся совсем!
К примеру, Lombok не работает.
На самом деле проапдейтили, даже в CHANGELOG написали, только поленились выпустить свежую версию почему-то. А вообще ты донат занёс людям или только требовать умеешь? ;-)
Хотя, конечно, вру. "Some initial work on supporting JDK10" звучит совсем неубедительно.
Я умею не использовать у себя Lombok! :-)
Alt+Enter, Getter and Setter, Enter, Enter, как-то так. А ещё можно расчехлить JavaParser и переехать им исходники в цикле, если совсем ленивый.
Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…
Почему это нужно всегда делать, я так и не понял. Но карго-культу продолжаю следовать…
Не вы один… /смотрит с укором на половину своего кода, построенного по принципу карго-культа, вздыхает с мыслью «ну зато работает збс»...
Объекты надо любить! Раз в год бывает нужда таки расширить геттер или сеттер и вставить проверку, например.
Насколько это оправдывает геттеры/сеттеры — хз.
Это же не тру ООП!
Ну ещё ломбок генерит конструкторы, и это круто работает с новым Спрингом — можно писать private final поля, Ломбок сгенерит конструктор и спринг через конструктор вставит бины.
Это же не тру ООП!
Почему? Наоборот, SOLID во все поля! Под задачу валидации выделен отдельный класс, который несет только одну ответственность :D
И валидацию параметров конструктора ломбок прикрутит? Если у меня class Range { private final int from, to; }
и инвариант from <= to
, куда мне инвариант впихнуть?
Мы начали его использовать, когда поля постоянно менялись, была такая дикая фаза. Сейчас поспокойней, но Lombok как-то прижился.
Да ладно. И ещё кучей вещей не пользоваться. Сидеть на голой джаве.
Есть подозрение, что сломан не только Lombok. Просто он самый первый в цепочке компиляция-запуск. И дальше я пока не прошел, проще подождать немного, пока пофиксят.
В прошлый раз, уже после выхода 9, были проблемы у jooq. Logstash вроде бы до сих пор на 9 не запускается.
Блин, похоже, удел ынтырпрайза — LTS :(
Утилита javah больше не нужна, потому что нативные заголовки теперь может делать javac
Очень интересно. Я правильно понимаю, что если у меня сорцы на котлине, то теперь хрен мне, а не jni? Спасибо тебе, Оракл, что заставляешь в полностью котлиновском проекте заводить единственный джавовый класс со всеми нативными методами.
Можно попробовать выделить external методы в отдельные классы, собирать их с jvmTarget=1.8, и потом натравливать на них javac из старых версий JDK
Java 10 General Availability