Ключевое слово «var» в Java: пожалуйста, только не это

Ключевое слово var

Прошедшее 8-е марта для разработчиков Java выдалось особенно насыщенным. Причиной тому послужил новый JEP 286: Local-Variable Type Inference, который предлагает ввести ключевое слово var, избавляя нас от необходимости явно указывать тип локальной переменной:

var unbufOut = NetUtils.getOutputStream(sock);

вместо

OutputStream unbufOut = NetUtils.getOutputStream(sock);

А на днях подоспели и результаты опроса разработчиков, которые недвусмысленно показали — var в Java быть. Хорошо это или плохо?

Судя по лентам Твиттера и результатам опроса, первая реакция многих разработчиков (включая меня) была такой:

No god please no

Я решил разобраться, почему этот JEP вызывает у меня отторжение.

Почему «нет»


Java всегда была и остается достаточно консервативной платформой. Иногда этот консерватизм реально ограничивает пользователей. Нашумевшая история с выпиливанием Unsafe, проникновение которого во многом есть результат игнорирования нарастающей потребности в низкоуровневом API, — ярчайший тому пример.

Консервативность языка, напротив, давала Java ряд преимуществ. Во-первых, это низкий порог вхождения. Базовый синтаксис языка очень компактен, и прост в изучении. Во-вторых, это экспрессивность. Языки, напичканные всевозможными фишечками, вроде Scala и C#, позволяют писать совершенно нечитаемые конструкции. Смешайте лямбды, type inference и имплицитный return, и читателям вашего кода придется хорошенько напрячься. В Java написать нечитаемый код значительно сложнее.

Отсюда и главная претензия к var — риск снижения читабельности. На практике мы «понимаем» код во многом благодаря трем составляющим: типы переменных, имена переменных, и имена методов. Повсеместное (а в худшем случае — бездумное) использование var, уничтожит первую из них. Для поддержания читабельности на том же уровне, придется больше внимания уделять именам методов, так как их вклад в восприятие кода значительно возрастет.


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

Люди пишут в опроснике:
Scope is small, so will only give more confussion to new developers. The typing of the boiler plate is tackled by decent IDEs.
We have IDEs so I don't care

В комплексе все это делает преимущества type inference достаточно сомнительными.

Особенно непросто придется любителям разработки «в блокноте». Существует мнение, что данный аргумент высосан из пальца, так как все пользуются IDE, а условный «notepad» — это удел фриков, неадекватных работодателей и джуниоров, пишущих свой первый «Hello, world!». Это не совсем так. IDE — это инструмент работы с кодом. Но сам код находится в других местах: в файлах, в mail-листах, в баг-трекерах, на форумах, и так далее. Когда вы открываете JIRA-тикет с куском кода, Вы сначала читаете его в браузере, верно? Поэтому чтение кода вне среды разработки — совершенно нормальная и распространенная практика, которой занимаются едва ли не все разработчики. Есть вполне обоснованные опасения, что var этот процесс затруднит.

I'm not sure if it will not increase the difficulty of code review
I code both in Java and C# and sometimes and need to work with C# code where people have used var. It makes it a lot harder to see the type of a variable for no or very little gain.

Почему «да»


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

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

С развитием языка ситуация ровно та же. Появляется новый инструмент. Какое-то время люди учатся, притираются, делают ошибки. Появляются новые тренды и подходы, которые находят своих сторонников и противников. Наконец, образуются устоявшиеся практики, которые применяют в конкретных проектах.

Поэтому до начала массового использования var, достаточно сложно сказать, насколько много проблем и неудобств оно принесет. Но мы можем обратиться к языкам, которые уже имеют type inference — C++, C#, Scala… давайте иначе — а в каком известном вам мейнстримовом языке этого нет? Лично у меня нет информации о том, чтобы какой-то язык серьезно пострадал от type inference. Кто-то пользуется, а кто-то нет, кому-то нравится, а кому-то нет, вот и все.

Ради эксперимента я походил по кодовой базе Akkа и Spark. Намеренно искал места, в которых было бы сложно разобраться конкретно из-за type inference. Субъективно — не нашел. В подавляющем большинстве мест смысл переменной был легко понятен из контекста благодаря именам переменных и методов. По моим ощущениям, хороший код не пострадает. А вот плохой код может стать еще хуже. Ну и бог с ним.


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

Мне всегда было достаточно сложно понять мотивацию больших и сложных проектов, использующих JVM-based языки. Например, что получили Akka и Spark от использования Scala? Издержки очевидны — дополнительный барьер между продуктом и миллионами Java-разработчиков. А польза? Добавление новых фич, начиная с такой важнейшей вещи, как лямбды, и заканчивая относительно бесполезным var, позволит прекратить разброд и шатания, и вновь сконцентрирует комьюнити вокруг непосредственно Java. Это безусловный плюс.

Thanks so much! This will remove yet another death-by-a-thousand-cuts issues w Java that drive people to seek alternatives
Please simplifiy the Java language (and JavaEE in general)! Type inference is a great step into the right direction.

Итог


Исключительно субъективно: с точки зрения разработчика это «никакая» фича. Пользы мало, вреда мало. Но в целом для языка это однозначный шаг вперед. Один из многих, которых мы с нетерпением ждем:
Is there way to add union and intersection types in Java?
Could you consider the introduction of case classes (like in Scala)?
when do you expect primitive types be allowed in generics?
Remove getters and setters.
When will we have async/await feature in Java ( like c# and f# ) ?

Но лично я пользоваться var не хочу. Блокнот сподручнее.
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 326
  • +18
    В вашем примере, безусловно, использование var неуместно:
    var unbufOut = NetUtils.getOutputStream(sock);
    Но вот пример, в котором ему самое место:
    FileOutputStream fos = new FileOutputStream("t.tmp");
    В C# так сделано и это удобно.
    • –15
      А мне нравится использовать полные типы в строках вида
      SomeClass something = new SomeClass();
      
      потому что после того, как я написал левую половину, автодополнение дописывает за меня правую — мелочь, а приятно.
      • +12
        Наверное надо еще потребовать обязательного явного приведения типов :), чтобы вы писали
        Window windows = new
        А IDE вставляло еще больше избыточного кода
        Window window = (Window) new Window()
        • +3
          В IDE 4 опции:
          1) Отображать var v=new T(); как T v=new T();
          2) Автоматически преобразовывать var в типы
          + две обратные покроют
          все необходимые пожелания всех и каждого.

          Другое дело, что почти никто в настройки IDE не полезет, а вот на хабре холиварить будет часы напролет. И да. Я тоже так сделаю ;)
          • 0
            А это зачем? Не понял вашей логики.
            • +6
              Ну если человек испытывает удовольствие от того, что IDE дописывает избыточный код, который можно вообще не писать, язык должен предоставить ему больше удовольствия — требовать больше тупого дубрирования
          • +6
            Пишите: new SomeClass().var жмякаете таб — ИДЕ генерирует
            var something = new SomeClass(); с фокусом на названии переменной которую можете изменить.
            • 0
              Это ReSharper.
              • +2
                Только что проверил, Idea так же делает.
                • +3
                  Так контора-разработчик одна.
              • 0
                Можно даже проще — нажать Ctrl+Alt+V сразу после выражения ("extract variable").
                • 0
                  Это гениально. Я о таком даже не предполагал. Спасибо.
                  • 0
                    new SomeClass(); а потом Ctrl + Alt + V
                    • +1
                      Раскорячивать пальцы проще, чем написать var? :)
                      • 0
                        Так ведь Idea/Resharper довольно адекватные имена переменным дают.
                  • +1
                    А какой смысл, если вы уже написали левую половину (т.е. само имя класса и имя переменной)? С var вы напишите примерно столько же...
                    • +1
                      А я вообще люблю писать
                      List<SomeClass> list = new ArrayList<SomeClass>();

                      И var из той же оперы.
                      • +2
                        а var в этом случае будет List или ArrayList?
                        • 0
                          ArrayList
                          • –1
                            Ну вообще-то и List-ом, собственно, он тоже будет, не?
                            • +1
                              Будет, но выведется конкретный тип ArrayList. Если пытаться выводить до интерфейсов, то так можно дойти до вывода в Object.
                              • +1
                                Ну это то понятно. Тем не менее неспроста (канонично) слева пишется List, а справа ArrayList. Т.к. ArrayList — это по сути указывается конкретная реализация контракта. Это было к "var из той же оперы" в основном сказано.
                                • 0
                                  Как часто вам в локальном скопе метода важно сокрытие реализации контракта?
                                  Если метод настолько большой, что это играет роль, то мне кажется, explicit/implicit тут уже не спасёт.
                                  • 0
                                    Как часто вам в локальном скопе метода важно сокрытие реализации контракта?
                                    В локально скопе — не так уж часто. Я потому и написал про «канонично». Но я лично всегда так пишу и считаю хорошим тоном.
                      • 0
                        Если вы используете IntelliJ то вы делаете это неправильно — сначало нужно писать правую часть, нажать alt enter и enter(первый пункт всплывающего меню будет — introduce local variable).
                        • 0
                          Согласен тем, что при простом вызове конструктора проще использовать var. Ведь если писать полное имя типа в объявлении переменной IntelliSence всё равно будет подсказывать с нуля и придётся половину имени типа набирать.
                          Если вспомнить, то var появился в C# 3.0 вместе с лямбдами и LINQ. И первую очередь он нужен именно там, чтобы не писать моструозные конструкции вроде: IEnumerable result =…
                          В C++11 auto в целом тоже для тех же целей добавили (с ужасом смотрю на все эти шаблонные итераторы).
                          • +2
                            Нет. var в первую очередь нужен для работы с анонимными типами, к-ые логично появляются в LINQ при операции проекции (Select)
                            • 0
                              Да, согласен. Про проецирование я что-то забыл. В этом случае уже без var даже написать полное имя типа нельзя. Не знаю есть ли такое в Java, но с var может и оно появится )
                        • 0
                          Да, пожалуй случай когда NetUtils возвращает FileOutputStream это действительно весьма странный кейс, когда было бы неплохо увидеть, что тип переменной таки FileOutputStream.
                          Но вообще для меня видится довольно странным заявление, что var приносит мало пользы и больше вреда. Это где-то аналогичное тому, что говорить что понижение типа это вредно (типа так: OutputStream unbufOut = NetUtils.getOutputStream(sock);). Зависит от случая к случаю.
                          Вообще, в строке приведенной автором для примера я вижу две проблемы корректного именования и проблему того, что зачем-то метод возвращает максимально специфичный класс. Видать джависты не умеют в корректный нейминг и ООП.
                          • 0
                            Но вообще для меня видится довольно странным заявление, что var приносит мало пользы и больше вреда.

                            В статье написано:
                            Пользы мало, вреда мало.
                          • +6
                            Когда я вижу такое:
                            var unbufOut = NetUtils.getOutputStream(sock);
                            То мне не очень надо знать, какой именно тип представляет обой unbufOut (кстати, обясните, пожалуйста, кто дал такое имя переменной и какомй naming convention оно следует).
                            Я уже вижу что это именно stream, скорее всего полученный по сокету. Для общего понимания алгоритма это должно быть не важно. Если мне понадобится знать тип, я просто наведу курсор на переменную.
                            А если мне понадобится знать, что именно делает getOutputStream, я нажму f12 и не потребую к каждому вызову метода приписывать полный текст его реализации прямо в исходнике.
                            • –6
                              Если мне понадобится знать тип, я просто наведу курсор на переменную.
                              А если мне понадобится знать, что именно делает getOutputStream, я нажму f12 и не потребую к каждому вызову метода приписывать полный текст его реализации прямо в исходнике.

                              ТО есть часть статьи про "много работы ведется вне IDE" — вы проигнорировали.
                              Я вот на днях закончил работу по протированию на Андроид 44 плагинов для проекта с исходниками примерно на 600 файлов. Все из которых я вынужден был редактировать в Notepad++ в силу специфики рабочего окружения.
                              Куда мне в Notepad++ навести мышку чтобы узнать тип и где нажимать F12?
                              • +2
                                Тогда да, вам нужно объявлять типы (вместо наведения мышки) и рядом каждым вызовом функции писать ее полный текст в комментах (вместо F12).
                                А что за особенности окружения?
                                • –4
                                  "Мне" надо?
                                  Неужели вы думаете, что программисты только со своим кодом работают?
                                  • 0
                                    Ну значит вам нужно чтобы все так делали :)
                                    • 0
                                      А здесь только я с кодом работаю не только в IDE?
                                      • –1
                                        Я не говорил вообще ничего про остальных
                                        • +1
                                          А это не только к вам вопрос, на самом деле.
                                          Минусующих меня за утверждение, про разработку вне IDE — достаточное количество и под постом что я выше написал и в карме. Так что я делаю вывод, что программистов работающих в идеальном мире где всегда есть IDE "которая подскажет" — больше чем тех, кто с реальными проектами работает в реальных условиях. :))
                                          Ситуация о которой я ниже писал — это только личный пример и исключение. Но на своей практике я таких исключений уже, наверное, с сотню видел. Когда приходится работать с кодом в некомфортных условиях за пределами такой удобной IDE. И мне странно что есть люди, которые с этим еще не сталкивались...
                                  • 0
                                    Особенности окружения:
                                    Плагин испольуземый разработчиками для ведения проекта при сборке и деплое проекта выводит модальное окно, которое блокирует работу с IDE(Видимо чтобы пользователь-идиот не сохранил какой нибудь файл во время сборки не сломал сборку). А еще этот же плагин(чтоб его разработчики в аду горели) при добавлении или удалении файла в проекте инициирует его ПОЛНУЮ пересборку.
                                    Наверно плагин прекрасно себя показал при работе с мелкими проектами… Но когда проект на несколько тысяч строк…
                                    Пока один проект с одним модулем собирается и деплоится — портирование другого ведется в блокноте, чтобы время не терять.
                                    • 0
                                      А как от отличает блокнот от IDE? Нельзя ли сделать чтобы плагину не было видно IDE и он его не блокировал? Это плагин для чего?
                                      • 0
                                        Можно просто открыть второй инстанс IDE и в нем работать. Благо плагин не блокирует доступ к файлам.
                                        Но по причинам которые я в сообщении ниже написал — это не имеет смысла. IDE все равно кастрированная, и не даст преимущество перед блокнотом.
                                        Плагин — собственно отвечает за сборку и деплой проекта под Андроид.
                                        • 0
                                          нельзя ли генерировать проект отдельно для плагина или наоборот из проекта плагина отдельно генерировать проект для IDE? Т.е. отвязать вообще IDE от плагина, как от блокнота.
                                          • 0
                                            Думаю что нет. Плагин призван дать возможность писать в MSVS под Андроид и без него студия вообще не умеет Java код понимать.
                                            В целом знакомство мое было с этой системой не долгим и уже закончилось, надеюсь и не возобновится. :)
                                            Так что я не могу ответить на такие вопросы, чтобы еще свежую травму не бередить. :))))
                                    • –1
                                      Ах, еще один прекрасный момент этого плагина:
                                      Он не переваривает большие проекты. Поэтому большая часть исходников прописана в мейкфайле, но отсутствует в самой IDE.
                                      Хорошо IDE их хотя бы при дебаге открывает. А так — даже кликнуть по переменной нельзя, чтобы по исходникам побродить. IDE просто не найдет куда перейти.
                                      Можно сказать: не пользуйте странные плагины…
                                      Ну так я и не использую. Заказчик использует. А я работаю с тем, что дают. Как и большинство разработчиков.
                                      • +1
                                        Э… И вы хотите чтобы язык приспосабливался к идиотизму вашего заказчика? А если я буду разрабатывать под досом, можно мне ограничение чтобы все файлы были 8.3?
                                    • 0
                                      > я вынужден был редактировать в Notepad++
                                      почему это вынужден?
                                      вас ктото заставлял редактировать именно в Notepad++? ваш внутренний голос?
                                      • 0
                                        А где надо было?
                                        • 0
                                          Надо было идти пить чай/кофе. Если такая среда разработки — требование клиента, то и платить за такую радость должен клиент.
                                          • 0
                                            Так он и платит.
                                            Я ему не говорил что меня что-то не устраивает и не планирую. Потому что есть работа, есть ее оплата. А комфорт и прочие вещи — это моя проблема, а не клиента.
                                            Это пример вполне рядовой. Обычно всё не так экстремально, но работа с кодом вне IDE — это обычное дело. И это надо учитывать.
                                            • 0
                                              Нет, ну если тебе нравится этот геморрой — то пожалуйста. Фишка-то как раз в том, что рынок за программистов (не во всех сферах, но в большинстве существенных). Да и в любом случае — комфорт очень важен при программировании: меньше потенциальных ошибок, лучше погружение в задачу.

                                              Поэтому я предпочитаю использовать особенности рынка для своей пользы — мне вот даже на одномониторной станции некомфортно… Что уж говорить о работе вне IDE… хотя совсем таковая не исключается — различные сниппеты в интернете, код-ревью вне IDE и просмотр коммитов вынуждают пользоваться только подсветкой синтаксиса… но ведь в этом режиме и глубокого погружения, обычно, не требуется.
                                              • 0
                                                Еще вопрос, почему можно было установить Notepad++ но нельзя было установить Eclipse ?
                                            • 0
                                              в vim — очевидно же
                                          • +1
                                            > ТО есть часть статьи про «много работы ведется вне IDE» — вы проигнорировали.

                                            Нет, это вы проигнорировали, что это не важно в 146% случаев.

                                            Если вы хотите сказать иное, то сначала озвучивайте конкретный кейс, который вы почему-то делаете вне ide. Потом уже можно будет обсуждать ценность такого кейса.

                                            Например, если вам нужен тип на ревью — вам не нужен тип, вам нужно джуниору всучить «clean code».
                                            • +1
                                              А много ли меняется вне IDE?
                                              Одно только имя типа ничего не дает. Вы все равно видите только тот его интерфейс, который выражен в читаемом коде. Если вам нужно узнать что-то большее — вам придется искать объявление типа по проекту, ведь «не IDE» не умеет переходить к типу, по имени или без него.
                                              Конечно, если есть документация в которой легко находится тип по имени — то тут проще. Но этим же способом можно найти саму функцию, в описании которой скорее всего есть прямая ссылка на возвращаемый тип. Тем более, что если нам неизвестен возвращемый тип, то и остальные знания о функции неплохо бы освежить/получить, так что нам даже по пути.
                                              В итоге, не такая уж большая разница получается, зато пользователям IDE (которых большинство) — профит.
                                          • 0
                                            После того, как var разрешат, вы уже не заставите разработчиков явно указывать типы в таких местах (var unbufOut = NetUtils.getOutputStream(sock); )
                                            Более того, на данный момент Решарпер в студии подчеркивает явное объявление типа переменной и предлагает использовать var.
                                            Вот если бы var ввели и разрешили использовать только в случаях, как во втором примере (FileOutputStream fos = new FileOutputStream(«t.tmp»); )
                                            • +1
                                              Ну да, египетские скобки в джаве можно заставить не писать, а var нельзя? Точно так же административными мерами решается, через внутренние стайлгайды, в них и пропишете что можно использовать только во втором случае.
                                          • +26
                                            Поначалу в C# тоже все плевались и были консервативны.
                                            Потом постепенно начли менять на var ОченьДлинныеИменаКлассов, потом начали менять всё кроме примитивов (int на var не экономит даже буквы), а сейчас все успокоились и полюбили var, вот и в жаве так же будет.
                                            P.S.: в плюсах я тоже везде леплю auto, ибо нефиг ;)
                                            • +2
                                              А мне нравится использовать полные типы в C#. Я их даже раскрашиваю разными цветами.
                                              • +2
                                                То, что везде пихают — не есть хорошо. И не надо слушать толпу, а то можно сойти на дискуссии про миллионы мух и JavaScript.
                                                ИМХО var, как и auto, уместны только при замене неприличных названий классов для временных переменных. Вроде тех же итераторов, которые на плюсах могут перерождаться во что-то, о чём пишут культисты в своих книгах. В остальных случаях всё же не стоит скатываться в php, да не обидятся на меня адепты синего слоника…
                                                • +8
                                                  учтите небольшую разницу между php/js и c#/c++: в первых внутри var может оказаться что угодно, во вторых — это вполне конкретный тип, просто мы его не называем.
                                                  • +1
                                                    У меня на работе был случай, когда приложение складывалось по банальной причине: автоматический вывод типа отрабатывал лучше, чем люди. И причина была банальной, в пылу копипасты, как и положено, сделали опечатку. А в итоге вызывалась не та перегрузка метода фабрики и всё, заверте.

                                                    Я не спорю с тем, что то был быдлокод, ибо копипаста — не метод, тем не менее ошибки бы не было, если бы вместо «auto type = foo()» был «int type = foo()». И от этого не застрахованы даже лучшие из нас.
                                                  • +4
                                                    Да ладно вам. Типизация от этого никуда не денется, а шума в коде меньше. Доверить веведение типов компилятору — правильная вещь. Вообще, эта фича во многих современных языках. Можно посмотреть на тот же Kotlin, на сколько оно становится компактнее. При чтении кода обычно незачем знать тип каждой переменной, при необходимости всегда можно навести мышкой на переменную и посмотреть тип.
                                                    • +1
                                                      Если вы про

                                                      var worker = new MyVeryFreakingAwesomeSuperSlowAndStupidMultithreadAsynchrousSQLWorker.HisCoolResult(kill,this,guy,please);

                                                      , то я за. Если вы про

                                                      int lososni(int);
                                                      byte lososni(byte);
                                                      tuna lososni(short);

                                                      var item = lososni(1);

                                                      , то, пожалуйста, Расмус Лердорф, перелогиньтесь.
                                                      • 0
                                                        Кстати говоря, я очень часто импортирую inner-classes. Вы спокойно можете сделать
                                                        import my.superpuperpackage.MyVeryFreakingAwesomeSuperSlowAndStupidMultithreadAsynchrousSQLWorker.HisCoolResult;
                                                        
                                                        ...
                                                        
                                                        HisCoolResult worker = new HisCoolResult(kill,this,guy,please);
                                                        • 0
                                                          Чукча не писатель, чукча — читатель. В том смысле, что я перевожу пару проектов с Java на плюсы в свободное от рукоблудства время.
                                                          • 0
                                                            Публичные вложенные классы — дурь последняя. Почти всегда — или нарушение принципов инкапсуляции или неудобный механизм использоваться. И статические импорты таких классов — всего лишь костыль для этого непотребства.
                                                            И да, я знаю, что этим болеет и несколько классов в JDK.
                                                            • 0
                                                              На мой взгляд это вполне нормальная группировка классов и интерфейсов по пространствам имён, когда пакет — слишком крупная единица группировки. Это никак не связано с инкапсуляцией. Импорт таких классов не требует слова static, вряд ли его можно назвать «статическим импортом». С точки зрения пользователя такой класс несильно отличается от класса в соответствующем пакете, только имеется напоминание, что он более тесно связан с другими классами в данном окружающем классе.
                                                              • 0
                                                                Ладно, в JDK это могло быть проблемой, но в кастомной библиотеке/приложении вложенные публичные классы какую роль должны играть? С учётом того, что слишком большой пакет — это тоже не очень хорошо (я бы даже сказал — плохо… но с JDK понятно — там сложно было осуществить качественную пакетную детализацию… да при сохранении обратной совместимости).
                                                                • 0
                                                                  Вот одна из причин. Если модули (Jigsaw) использовать пока нельзя, толстый пакет удобнее для управления видимостью. Из других пакетов можно использовать только public-методы и классы, тогда как из текущего пакета можно использовать package-private. При разработке библиотек большие куски кода не хочется выставлять наружу, но при этом хочется их переиспользовать в разных частях библиотеки. Поэтому раздутый пакет часто единственная альтернатива. И для дополнительной группировки используются классы. С Java-9 будет легче жить. Эта же проблема, кстати, важна для JDK: у них огромное количество package-private классов (и это очень хорошо), но при этом есть костыли для межпакетного доступа (типа SharedSecrets, это, конечно, плохо).
                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                    • –14
                                                      Отсюда и главная претензия к var — риск снижения читабельности

                                                      .
                                                      Вот! Святые слова! Именно так! Подобные штуки валят дескриптивность кода наповал. Главное, когда я доказываю знакомым плюсовикам, что аналогичная штука в C++ (auto) это зло злющее — они меня не понимают и говорят что это одна из крутейших фич в С++11.
                                                      .
                                                      Ну ладно плюсы, там есть пятиэтажные жуткие конструкции на шаблонах и итераторах в библиотеках и можно понять желающих скрыть эту жесть. Но Java — язык прикладной, не системный. Зачем?! Так трудно написать тип? Просто лени ради?
                                                      .
                                                      На мой взгляд var (auto, и все иже с ними) — волшебная палочка в руках ленивого говнокодера, с которой ему теперь даже не нужно утруждать себя обозначать типы. Берегитесь! var превращает карету вашего кода в тыкву нечитабельного ужаса.
                                                      .
                                                      П.С.: Приношу свои извинения за оффтоп с плюсами, просто накипло.
                                                      П.П.С: Что-то странное с разметкой в Хабре — съедаются энтеры (заменил точками в посте). В чём может быть дело?
                                                      • +3
                                                        Сам по себе var может быть удобен, если его использовать правильно и только в случаях когда точно понятно что за тип у переменной. Проблема с ним в том, что его сувать будут куда ни попадя, а там уже сиди и гадай — что ж за тип возвращается в той или иной функции. А если она ещё и интерфейс возвращает вместо конкретного типа…
                                                        Лично я не очень его жалую, и не использую обычно, потому что читабельность реально снижается.
                                                        • +1
                                                          Проблема с ним в том, что его сувать будут куда ни попадя

                                                          Вот-вот. Мне кажется, синтаксис языка должен быть в чём-то подобен хорошо спроектированной программе — в нём должна быть защита от дурака. Да и просто защита от человека, который прототипирует код. Я сам поддавался греху и использовал эту фичу как проектировал код. Типа: "а, поставлю-ка пока var, пусть будет — там точный тип проставлю". А потом: "так, ладно. Вот var, которому мы присваиваем… var. А, чтоб тебя!"
                                                          • +1
                                                            Так это и начинается :) Я тоже его пробовал использовать. Когда проект пишешь, то мысль "нужен тут var или нет" не является приоритетом, и получается лепишь его везде где можно.
                                                            • 0
                                                              Когда проект пишешь, то мысль «нужен тут var или нет» не является приоритетом, и получается лепишь его везде где можно.

                                                              Если с предыдущим вашим постом я согласен, то в данном случае это проблема разработчика, а не самой возможности. Посмотрел в своих проектах использование var:
                                                              1. Тип переменной указан при присвоении(using(var sw = new StreamWriter(path)), т.е. убираем дублирование информации);
                                                              2. Тип переменной известен из имени переменной (cancelButton, аналогично убираем дублирование информации);
                                                              3. При получении промежуточного звена LINQ выражения, если оно будет следом использовано для извлечения требуемых данных (т.е. информация о данном типе не имеет значения, т.к. это короткоживущая переменная, созданная по техническим причинам и используемая 2-3 раза на текущем экране кода).

                                                              В итоге VAR позволяет убрать дублирование информации или скрывает ненужную информацию, что не отражается на читаемости кода. Во всех остальных случаях обязательно использование имен типов, а порой и с пространством имен, если важно акцентировать внимание на библиотеку, из который используется данный класс (например, если мы хотим явно указать, что используем NLog в качестве логгера).
                                                              • +5
                                                                Я не противник var вообще, но вот пример из Tox:
                                                                public ToxData GetData(string password)
                                                                {
                                                                       ThrowIfDisposed();
                                                                
                                                                       var data = GetData(); //как выглядят эти самые данные?
                                                                       byte[] encrypted = ToxEncryption.EncryptData(data.Bytes, password);
                                                                
                                                                       return ToxData.FromBytes(encrypted);
                                                                }

                                                                или
                                                                var key = salt == null ? ToxEncryption.DeriveKey(passphrase) : ToxEncryption.DeriveKey(passphrase, salt);

                                                                Не очень-то и читаемо. Да, не проблема пойти в функцию, узнать что оно там возвращает, и потом пойти в тот самый класс и смотреть что в нём. А можно было сразу написать тип и не делать лишних движений.
                                                                А так конечно есть случаи когда его удобно использовать :) Только надо помнить что человек — не компилятор, и способности к инференции типов у него ограничены :)
                                                                • +3
                                                                  А так конечно есть случаи когда его удобно использовать :) Только надо помнить что человек — не компилятор, и способности к инференции типов у него ограничены :)

                                                                  Именно это я и имел в виду
                                                                  var key = salt == null? ToxEncryption.DeriveKey(passphrase): ToxEncryption.DeriveKey(passphrase, salt);

                                                                  А за такое использование я бы точно убил.
                                                                  • 0
                                                                    Убивать людей не стоит, но автор кода точно хотел написать на Scala с экспрешен семантик :)
                                                                    • +1
                                                                      А за такое использование я бы точно убил.
                                                                      Достаточно немного переформатировать код и не будет нужды кого бы то ни было убивать — возвращаемый тип прекрасно виден. Никогда не понимал, почему люди недолюбливают операцию тернарной альтернативы.
                                                                      var key = (salt == null)
                                                                      ? ToxEncryption.DeriveKey(passphrase)
                                                                      : ToxEncryption.DeriveKey(passphrase, salt);
                                                                      • –3
                                                                        Но ведь в данном случае достаточно было указать тип переменной и сразу код бы стал более читаемым, так как уже нет особой нужды смотреть на реализацию. Да и результат DeriveKey не особо понятно какого типа: может строка, а может специальный тип. Но это уже скорее личные придирки.
                                                                        А в целом это все дела личных предпочтений каждого разработчика.
                                                                    • 0
                                                                      Я не знаю что такое Tox. Судя по коду приведенный кусок получает откуда-то данные и шифрует. Я ожидаю, что у data скорее ксего тип ToxData
                                                            • +32
                                                              То есть код вида:
                                                              NetUtils.getOutputStream(sock).write("hello");

                                                              • вас не смущает, а эквивалентный:

                                                              var unbufOut = NetUtils.getOutputStream(sock);
                                                              ounbufOut.write("hello");

                                                              • адский ад? Может и первый вариант запретим? Там же не понятно какой тип возвращается! В одной строке должно быть не более одного вызова метода!
                                                              • +2
                                                                Хм… А ведь справедливо. Не задумывался о подобной аналогии с цепочечным вызовом методов. Спасибо, подумаю об этом.
                                                                • +1
                                                                  В первом варианте нам не требуется держать в голове контекст, так как возвращаемое значение используется сразу же, по цепочке, во втором же случае — нам нужно помнить тип unbufOut до самого конца области видимости.
                                                                  • 0
                                                                    В джепе кстати такой же пример в качестве аргумента за:
                                                                    var path = Path.of(fileName);
                                                                    var fileStream = new FileInputStream(path);
                                                                    var bytes = Files.readAllBytes(fileStream);
                                                                    так и бряки приятнее ставить
                                                                    • 0
                                                                      Согласен, привязка брейкпоинтов к строкам, а не ленсемам — это боль.
                                                                  • +40
                                                                    По опыту: если у вас var снижает читаемость, значит у вас гораздо большие проблемы с кодом, чем читаемость.
                                                                    • +3
                                                                      Проблема скорее не в написании своего кода, а в получении чужого в наследство за три недели до релиза, куда нужно добавить новую фичу
                                                                    • +1
                                                                      Если б вы не сказали — не заметил бы точки;) в остальном плюсую.
                                                                      • +1
                                                                        На мой взгляд экзепшоны — волшебная палочка в руках ленивого говнокодера, с которой ему теперь даже не нужно утруждать себя написать и проверить возвращаемое значение.
                                                                        На мой взгляд функции — волшебная палочка в руках ленивого говнокодера, с которой ему теперь даже не нужно утруждать себя написать ещё одну реализацию сортировки.
                                                                        • 0
                                                                          Что ж. Вывод из всего случившегося на будущее мне и иже с ними: нужно быть осторожнее при высказывании категорических субъективных и непроверенных суждений в трендовых постах… Вроде было очевидно — но попался. Спасибо сообществу за урок.
                                                                        • +2
                                                                          А как быть если мне нужно в возвращаемом значении иметь не реализацию класса, а его интерфейс?
                                                                          И вообще это "замена вместо" или "дополнительная фича"?
                                                                          • +1
                                                                            Дополнительная. Какие сомнения в этом?
                                                                            Слишком часто надо явно задавать тип переменной, чтобы его везде можно было заменить на var.
                                                                            Это надо по сути другой язык делать.
                                                                            • 0
                                                                              Конечно же фича.
                                                                            • +2
                                                                              У var есть польза, но я понимаю людей которые не могут ревьювить шарповый код с обилием varов. Банально разница в том, к какому подходу привык человек. Есть подход, основанный на концепции "важен код, т.е. действия, которые мы совершаем" и есть подход, основанный на концепции "важны типы, т.е. то, с чем мы работаем". Оба подходы имеют право на жизнь и более того, разные подходы по разному ложатся на разные задачи.
                                                                              Но прикол в том что отсутствие varа и тех же лямбд (ранее) мешал следовать первому подходу. Тогда как в грамотных руках var и лямбды делают код более читабельным, а не наоборот.
                                                                              Можно сравнить код с статьями/книгами. Слишком много воды — трудно уловить суть. Слишком мало воды — мозг либо отвык, либо просто не может слишком долго концентрировать на важных вещах. Оптимальный баланс найти трудно.
                                                                              • –6
                                                                                А можете рассказать как раскрывается информация о типах когда мы, например, записываем результат функции? Например, вот такой вот код:
                                                                                .
                                                                                var theStream = openStream();

                                                                                .
                                                                                Что именно за поток возвращает функция?
                                                                                .
                                                                                Ясно что есть контекст, но он может разрываться тем, что тебя отвлекли от кода или пришёл тикет на фикс какой-то другой срочной баги… Я уже не говорю о случаях, когда код был порефакторен кем-то другим (например, человек заменил значение, которое openStream() возвращает — а var остался).
                                                                                .
                                                                                Ясно также, что по-хорошему нужно точнее именовать метод. Но, на мой взгляд, подобные вещи будут приводить к тому, что имена переменных и функций начнут включать в себя ту самую "воду", которая до этого обозначала тип. Особенно когда речь идёт о больших проектах.
                                                                                .
                                                                                П.С.: Извиняюсь за точки — выше писал, какая-то фингя с проставлением энтеров между строками на хабре.
                                                                                • +5
                                                                                  Что именно за поток возвращает функция?

                                                                                  Зачем именно это знать? Можете привести пример кода для понимаения которого недостаточно знать, что это поток, а нужно знать конкретный его тип?
                                                                                  • –7
                                                                                    Ну, пример навскидку. Например, у нас есть адова прорва разных потоков, но некоторые реализации имеют особые методы и в коде был как раз тот случай. Что-то в духе:
                                                                                    .

                                                                                    NewSpecificWebStream theStream = createStream();
                                                                                    _IPCache = theStream.getIP();

                                                                                    .
                                                                                    Если мы меняем NewSpecificWebStream на var, то в случае рефакторинга (например, смены типа, возвращаемого из createStream() ) могут полезть ошибки — да, времени компиляции, но от этого всё равно не особо внятные. Таким образом, var не будет бить по голове только там, где возвращаются интерфейсные классы — да и то, очередной рефакторинг всё равно может привести к печальным последствиям.
                                                                                    • +1
                                                                                      Какие не особо внятные, какой рефакторинг, приведите конкретный пример
                                                                                      • 0
                                                                                        Ну, например, есть вот такой вот код:
                                                                                        var theStream = createStream();
                                                                                        _IPCache = theStream.getIP();

                                                                                        createStream() возвращал NewSpecificWebStream. А потом решил заменить возвращаемое значение на просто WebStream, у которого нету метода getIP() или этот метод называется по-другому. И рефакторинг при этом провели не мы, а кто-то другой в столюдной компании. При сборке в случае если бы вместо var был бы тип NewSpecificWebStream, ошибка возникла бы в строчке вызова createStream() — несовместимость типов. А с var ошибка возникнет в месте вызова метода, и придётся прыгать к декларации переменной, а потом ещё и смотреть тип, возвращаемый createStream().
                                                                                        Возможно, пример немного надуманный — если честно, у меня достаточно небольшой опыт работы с var — но когда я впервые услышал об этой фиче, мысли вроде такой заставили меня очень осторожно смотреть на var.
                                                                                        • 0
                                                                                          Вы поменяли тип возвращаемого значения, вам показали то место, где использовался тот факт что тип другой. Если бы там, например стояла декларация типа createStream явно, то возможно getIP мог бы не использоваться, но при этом все равно ругань была бы. Вам бы пришлось проанализировать все такие места — действительно ли он использует что-то из NewSpecificWebStream. Мне кажется, с учетом того, что надо делать маленькие методы, предпочтительней var
                                                                                          • 0
                                                                                            Хуже было б если у него был getIP, но делал что-нить нечто иное.
                                                                                        • +4
                                                                                          Я не понимаю, почему ошибки не полезут, если мы оставим тип явно. Я также не понимаю, почему ошибки для кейса var будут менее понятными, чем ошибки для кейса createStream().getIP() (т.е. когда мы объединяем цепочку вызовов).
                                                                                          • –3
                                                                                            Если тип будет прописан явно, то ошибки полезут тоже, естественно. Но когда мы глянем декларацию переменной, для вызова которой возникла ошибка — то мы увидим в коде не невнятный var, а конкретный тип, для которого выскочила ошибка.
                                                                                            Про вызов методов один за другим отписались выше, это справедливое замечание… Правда, чуть поразмыслив, я вспомнил, что в таких случаях — особенно если код незнакомый — приходится-таки прыгать по декларациям методов, чтобы смотреть возвращаемые функциями типы, что раздражает, и не хотелось бы получить подобный эффект ещё и для локальных переменных.
                                                                                            • +1
                                                                                              Если сравнивать именно читаемость, то такой подход хорош только в случае, если важно именно получение IP, а создание потока не имеет логической ценности для дальнейшего кода. Так, мы знаем только лишь, что здесь получаем IP из некого потока. Но если потом мы хотим использовать поток и далее, к примеру написать еще пару функций с его использованием, то нам нужно знать тип потока. Читая чужой код вы, не узнав тип, не сможете правильно его использовать, а, значит, придется либо разбираться в коде, либо посмотреть через подсказки IDE. Просто попробуйте модифицировать чужой код и сразу поймете чем он плох)
                                                                                              PS: в принципе, var вообще можно убрать и писать что-то вроде: IP = createStream().getIP();. Только вот это какой-то скриптовый язык получится.
                                                                                        • +2
                                                                                          Что именно за поток возвращает функция?

                                                                                          А зачем вам это знать? Я правда не понимаю, объясните
                                                                                          Я уже не говорю о случаях, когда код был порефакторен кем-то другим (например, человек заменил значение, которое openStream() возвращает — а var остался).

                                                                                          И что случится плохого, если другой человек поменял возвращаемый тип метода openStream?
                                                                                          Вы, кстати, не думали о таком концепте: иногда необходимо, чтобы тип переменной был жестко связанной с типом выражения? Например в c++ есть decltype.
                                                                                          Ясно также, что по-хорошему нужно точнее именовать метод. Но, на мой взгляд, подобные вещи будут приводить к тому, что имена переменных и функций начнут включать в себя ту самую «воду», которая до этого обозначала тип. Особенно когда речь идёт о больших проектах.

                                                                                          Т.е. по вашему лучше определение переменной в видеFileInputStream fos = ... нежели var inputStream = ...?
                                                                                          • +2
                                                                                            Справедливости ради.
                                                                                            А зачем вам это знать? Я правда не понимаю, объясните

                                                                                            Ага, я тоже так в первый момент подумал. Только вот это InputStream или OutputStream?
                                                                                            • 0
                                                                                              А если у вас две переменные (одна InputStream, другая OutputStream), вы как их различать будете? По имени или будете каждый раз бегать глазами к определению переменной?
                                                                                              • 0
                                                                                                Так я же не отрицаю что имя отвратное. Я лишь о том, что в данном конкретном говнокоде явный тип бы помог. Хотя, на самом деле, там все равно парой строчек ниже скорее всего будет read или write.
                                                                                                • –2
                                                                                                  Ну так научитесь именовать чтоль переменные тоже правильно, а не только типы. Или вы аппелируете к тому, что разработчики стандартной либы более правильно именуют типы, чем разработчики вашего проекта переменные?
                                                                                                  • 0
                                                                                                    Как известно, с именованием всегда проблемы. На самом деле, я ни к чему не апеллирую. Более того, сам в опросе проголосовал за var + val. Т.к. считаю что должен быть простой способ делать final переменные (забавное словосочетание) чтобы провоцировать подход "final by default". Свой же первый коммент я написал исключительно
                                                                                                    Справедливости ради.

                                                                                            • –2
                                                                                              Т.е. по вашему лучше определение переменной в видеFileInputStream fos =… нежели var inputStream = ...?

                                                                                              Нет. На мой взгляд имя типа и имя переменной несут разные смысловые нагрузки. Тип говорит о том, чем вообще является переменная, имя переменной говорит о том, какое смысл она несёт в контексте места её использования. Если говорить про идеальное именование — то хорошим именованием, на мой взгляд, было бы что-то вроде FileInputStream theSavingStream =… (например, если вызов в рамках какой-то функции для сохранения данный на жёсткий диск).
                                                                                              • +4
                                                                                                И все же джависты не умеют в корректный нейминг
                                                                                                FileInputStream theSavingStream

                                                                                                Теперь я гораздо более хорошо понимаю почему вы считаете, что var это плохо
                                                                                                • –1
                                                                                                  Оу, да. Описался. Справедливо. Ну, считайте, там theLoadingStream и метод для загрузки чего-нибудь
                                                                                        • 0
                                                                                          Мое суждение очень локально. Я занимаюсь разработкой под Android уже более 5ти лет. Все мы знаем что нативный язык — это Java. Но в последнее время стал писать на Kotlin. Так там как раз такой синтаксис (val/var). Так что никакого отчуждения нет.
                                                                                          • +1
                                                                                            var — очень годная, полезная и нужная вещь. Java все-таки прогрессирует и медленными шажками идет в правильном направлении.
                                                                                            После года ежевечернего использования Scala объявление переменных с множеством дженериков в Java кажется сущим адом.
                                                                                            Программируя на Scala, почти никогда не использую явное объявление типов. Всегда понятно по имени переменной, какой у нее тип. И Idea конечно же подсказывает при автокомплите.
                                                                                            • –38
                                                                                              Прощай, проверка времени компиляции.
                                                                                              Здравствуй, ошибка времени выполнения, "внезапно" уронившая прод.
                                                                                              • +15
                                                                                                Если оно будет реализовано как в C#, то var можно использовать только в тех местах, где тип известен во время компиляции.
                                                                                                • +13
                                                                                                  Прочитайте про то, чем отличается вывод типов в статической типизации от динамической типизации.
                                                                                                  Ознакомьтесь с каким-нибудь языков, где выводов типов еще больше. (Haskell, F#)
                                                                                                  • –9
                                                                                                    Читал, знаком, и что? В Haskell статическая типизация. Он у вас даже не запустится, если тип нельзя было узнать во время парса.
                                                                                                    Или вы хотите сказать что инференция типа во время компиляции — это динамическая типизация?
                                                                                                    • +7
                                                                                                      Перечитайте то, на что я отвечал и мой ответ. Что-то из этого вы не до конца поняли.
                                                                                                      • +2
                                                                                                        Не разобрался, подумал ответ мне :)
                                                                                                    • 0
                                                                                                      вывод типов в статической типизации от динамической типизации
                                                                                                      Верно заметили. Вот вспомнил Haskell и сразу понял.
                                                                                                    • 0
                                                                                                      Пример приведите пожалуйста, что именно вы собираетесь ронять в рантайме?
                                                                                                      На мой взгляд, единственный сильный контраргумент против var — это общепринятость использования интерфейсов в Java. Например:

                                                                                                      List<String> names = new ArrayList<>();
                                                                                                      Map<Long, String> map = new HashMap<>();

                                                                                                      А дженерик-параметры уже в Java 8 не нужно дважды указывать, поэтому в приведенном примере минимум дублирующей информации.
                                                                                                      С другой стороны, это же всего лишь локальная переменная — пусть будет классом, все честно. А в сигнатурах методов никто не мешает так и оставлять интерфейсы.
                                                                                                      • –2
                                                                                                        уже в Java 8
                                                                                                        diamond operator еще в 7 появился.
                                                                                                        Да, там выше написали про вывод типов.
                                                                                                        • +1
                                                                                                          По факту контраргумент — вопрос привычки. За пределы метода ArrayList всё равно не вылезет, а внутри метода вам большой разницы нет, особенно когда вы этого типа перед глазами не видите. Наоборот, если вы формируете список в методе и возвращаете его наружу, вам может захотеться в конце вызвать какой-нибудь trimToSize() для экономии памяти, поэтому более специфичный тип внутри метода может пригодиться.
                                                                                                        • +6
                                                                                                          Как всегда в подобных обсуждениях var/auto находятся люди только что вылезшие из бункера и не ознакомившиеся с описанием фичи, считающие что их любимый ЯП собираются испортить динамической типизацией из PHP, JS и т.п. :)

                                                                                                          • –3
                                                                                                            Этих людей стоит успокоить: динамическая типизация в джаве давно есть, только синтаксис адский :) Если на JS было бы
                                                                                                            var a = "abc";
                                                                                                            var b = a.replace("a", "b");

                                                                                                            То на Java будет
                                                                                                            Object a = "abc";
                                                                                                            Object b = a.getClass().getMethod("replace", String.class, String.class).invoke(a, "a", "b");

                                                                                                            Динамическая типизация в чистом виде!
                                                                                                            • +2
                                                                                                              Где в данном примере динамическая типизация? Здесь её как раз нет совершенно.
                                                                                                              • 0
                                                                                                                Ну-ка, объясните, в чём разница между динамической типизацией и reflection?
                                                                                                                • +1
                                                                                                                  Хм, в определениях? Я может не понимаю вопроса, но не могу придумать контекста, где это было бы одним и тем же или хотя бы чем-то похожим.
                                                                                                                  • –1
                                                                                                                    В том, что код:
                                                                                                                    var item = new { Age = 18, Name = «Ivan», LastName= «Ivanov» };
                                                                                                                    Console.WriteLine(item.Age);
                                                                                                                    Console.WriteLine(item.Name);
                                                                                                                    Console.WriteLine(item.LastName);

                                                                                                                    Будет преобразован компилятором в:
                                                                                                                    AnonymousClass_666 item = new AnonymousClass_666() { Age = 18, Name = «Ivan», LastName= «Ivanov» };
                                                                                                                    Console.WriteLine(item.Age);
                                                                                                                    Console.WriteLine(item.Name);
                                                                                                                    Console.WriteLine(item.LastName);

                                                                                                                    А теперь сравните его с рефлекшеном.
                                                                                                                    • 0
                                                                                                                      Это детали реализации, которые никого не волнуют в заданном контексте. В рефлекшне JVM тоже может сгенерировать нативные методы, если конкретный метод часто вызывается.
                                                                                                                      • 0
                                                                                                                        Вы в этом точно уверены? Да и руководство прямо говорит об обратном:
                                                                                                                        Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
                                                                                                                        docs.oracle.com/javase/tutorial/reflect/index.html

                                                                                                                        Если бы проблемы с Reflection не было, то и не было бы такой библиотеки, как ReflectASM.
                                                                                                                        • 0
                                                                                                                          Более того, приведенный XAHOK пример вообще не является динамической типизацией.
                                                                                                            • +17
                                                                                                              Просто смешно от консерватизма явистов. Никто не заставляет писать var везде — пишите там, где явно понятен тип из выражения справа, типа
                                                                                                              SomeClass.SomInternalClass<String, Integer> foo = new SomeClass.SomInternalClass<~>();
                                                                                                              var снижает читабельность? да у меня глаза кроваточат от строки выше.
                                                                                                              А вообще зачем этот динозавр когда есть котлин.
                                                                                                              • 0
                                                                                                                static import com.some.SomeClass.SomInternalClass;
                                                                                                                Котлин сыроват и после java выглядит набором свистелок. Вот тут о его проблемах написано подробнее.
                                                                                                              • +4
                                                                                                                Даже это по факту мелочи. А вот когда используешь функциональный стиль на всю катушку, возникают типы шире экрана (например, BiFunction<BiPredicate<String, Integer>, String, BiPredicate<String, Integer>>). При этом он нужен реально в пределах ограниченного скоупа.
                                                                                                                По факту автоматический вывод типов уже работает в восьмёрке для аргументов лямбд. Кто использует функциональное программирование на всю катушку, у того больше половины переменных — по факту параметры лямбд, и у подавляющего большинства тип выводится автоматом. По факту этот JEP — логичное распространение существующего механизма, а не что-то новое.
                                                                                                                Меня больше парит, что предложенные var и val визуально похожи. Я при заполнении анкеты предложил оставить var, а вместо val использовать const (благо это уже ключевое слово), но ко мне вряд ли прислушаются.
                                                                                                              • +1
                                                                                                                Интересно
                                                                                                                Есть код скажем такой
                                                                                                                var somevar = somevar2.getSome();
                                                                                                                И есть конструкция
                                                                                                                Some somevar = somevar2.getSome();

                                                                                                                Как в первом случае узнать какой реально тип я получаю для дальнейшей работы?
                                                                                                                И как в первом случае Ide найдет мне в контекстной подсказке список функций которые возвращают именно тот тип что объявленная мной переменная?
                                                                                                                • –1
                                                                                                                  найти где объявлено somevar2 получить ее тип. Найти у типа getSome, получить тип результата он и будет типом somevar
                                                                                                                  • 0
                                                                                                                    Ну то есть лишние телодвижения при работе с чужим кодом (или со своим который писал достаточно давно что бы уже забыть детали)
                                                                                                                    • +1
                                                                                                                      Если вы разработчик IDE, то да, если пользователь, то IDE это сделает для вас
                                                                                                                      • +1
                                                                                                                        Что ide сделает за меня?
                                                                                                                        Я смотрю на код с var и пытаюсь понять что я получил в итоге вызвав эту функцию и не вижу этого.
                                                                                                                        • +1
                                                                                                                          посмотрите, как выглядит работа с ide kotlin, например,
                                                                                                                          Как только вы вводите переменную сразу же подсказка с типом, еще обычно можно наводить просто мышкой и тебе расскажут все про идентификатор под курсором.
                                                                                                                  • +3
                                                                                                                    По типу результата метода getSome(), очевидно. В чем проблема?
                                                                                                                    Разница только в том, что если вы напишете

                                                                                                                    AnotherType somevar = somevar2.getSome();

                                                                                                                    Вы поймаете ошибку компиляции, что тип Some не может быть приведен к типу AnotherType. Как раз потому, что компилятор сравнит результат метода getSome() и объявленный тип переменной.
                                                                                                                    Больше никакой разницы нет.
                                                                                                                    • +2
                                                                                                                      И как в первом случае Ide найдет мне в контекстной подсказке список функций которые возвращают именно тот тип что объявленная мной переменная?

                                                                                                                      При парсинге кода IDE посмотрит, что возвращает somevar2.getSome() и var somevar будет именно этого типа.
                                                                                                                      • –1
                                                                                                                        Вы не поняли меня. Я про контекстную подсказку написал.
                                                                                                                        • +1
                                                                                                                          Это и контекстных подсказок тоже касается. Тип переменной x, объявленной в виде var x = getSome() выведется из типа возвращаемого значения getSome().
                                                                                                                          • +2
                                                                                                                            Еще раз

                                                                                                                            Я пишу int x = obj.*******
                                                                                                                            Вместо звездочек мне ide покажет список функций которые возвращают int

                                                                                                                            Если я вместо int пишу var то ide начнет мне отображать уже список всех доступных функций которых будет значительно больше