×

Почему Java все еще не торт. Yet

Всем привет. Месяц назад вышла Java 11. Все круто. 6-месячный релиз работает. Платформа действительно начала быстро развиваться и обрастать новыми фичами. Вот, например, полный список из 90 фич, которые появились в одинадцатке. В основном это изменения на уровне JVM, но, по сути, это фундамент для будущих плюшек.

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

Pattern matching

Пожалуй, единственная конструкция из всего списка, которую я использую почти каждый день:

if (obj instanceof Device) {
    Device device = (Device) obj;
    ...
}

Для нас, как разработчиков, вполне очевидно, что если мы сделали проверку на тип переменной и она прошла, то мы вполне можем оперировать переменной как объектом этого типа. Сейчас же мы постоянно должны приводить переменную к нужному типу явно. Уже даже появился JEP305 для этой задачи, который предлагает следующий выход:

if (x matches Device device) {
    // can use device here
}

Но, судя по всему, в ближайший год это не попадет в джаву. Остается только надеяться, что фичу не придется ждать 10 лет.

switch for class

Синтаксис не очень частый, но иногда просто бесит, что нельзя сделать простой:

switch (obj.getClass()) {
    case Integer.class:
        …
    case Long.class:
       ...
}

Лично мне не понятно, почему такая простая, казалось бы, операция все еще не поддерживается джавой нативно. Конечно, эту проблему всегда можно обойти полиморфизмом или пачкой if else или сделать class.getSimpleName() и свитч по строке, но это не так удобно. Да и по производительности явно не лучший вариант.

List<Integer> to int[]

Каждому разработчику известно чувство, когда он фокусируется, входит в поток и начинает эффективно колбасить. И вот все идет классно, пока не нужно сделать преобразование List<Integer> в int[] или наоборот. Нельзя просто так взять и преобразовать лист целых чисел в массив примитивов. Сейчас, чтобы это сделать, нужно или писать цикл преобразования:

int[] integerListToInt(List<Integer> integers) {
        int[] result = new int[integers.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = integers.get(i);
        }
        return result;
    }

Ну или через стримы:

int[] array = list.stream().mapToInt(i->i).toArray();

Оба варианта, очевидно, не самые оптимальные и удобные. Да и вопрос на СО, которому уже 10 лет с сотнями голосов и сотнями тысяч просмотров как бы намекает нам про актуальность. С преобразованием в обратную сторону — такая же ситуация.

Да, можно обойтись без примитивов и конструкция будет выглядеть получше, но все еще не очень:

list.toArray(new Integer[0])

new ArrayList(array)

Если отсутствие преобразования List<Integer> -> int[] еще как-то можно объяснить разными сущностями int и Integer, то отсутствие конструктора с массивом для ArrayList вообще не укладывается в голове. И почему за 20 лет существования языка нужно использовать:

new ArrayList<>(Arrays.asList(array))

вместо:

new ArrayList<>(array)

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

ConcurrentSet

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

ConcurrentHashMap.newKeySet()

Но, во-первых, про этот метод нужно знать, во-вторых, опять же вопрос удобства, ну и в-третьих, это не ConcurrentSet, а просто Set. А сам класс — некий KeySetView. Почти в любом большом опенсорс-проекте, который я видел, был свой ConcurrentSet.

Path API

Как только появилось новое Path API, я сразу на него перешел. И вот, 7 лет спустя, до сих пор каждый раз, когда мне нужно использовать это API — страдаю от этого. Вы не можете сделать new Path(), так как это интерфейс. А статических фабричных методов в классе Paths целых 2. И поэтому часто код с Path выглядит так:

Paths.get(dataDir.toString(),  folder);

вместо:

Paths.get(dataDir,  folder);

Это, конечно, не так критично, так как у Path есть метод resolve(), но в виду его специфики он не всегда подходит.

Вывод

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

А что вам не нравится в сегодняшней Java?

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn

Схожі статті




Найкращі коментарі пропустити

«единственная конструкция из всего списка, которую я использую почти каждый день»
То есть вы не понимаетте ООП и не умеете им пользоваться, но при этом рассуждаете о Java? Зачем?

239 коментарів

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.

Жаль конечно что никто не вспомнил что Oracle J2EE дропнул и отдал Eclipse’у.
Ну и J2EE стал таким же тупиковым как и сама Java.

Если вспомнить сколько у нас в стране «J2EE бородатых дядек», то их ждёт небольшой экзистенциальный кризис, как в том анекдоте про ExtJS.

Жаль конечно что никто не вспомнил что Oracle J2EE дропнул и отдал Eclipse’у.

Ну так спринг давно J2EE стек заменил. Так что это было предсказуемо еще 5 лет назад.

е-е-ем, а їх там ланцюгами прикували, до того J2EE?

Дмитрий, понимаю что не по теме, но
Нет такого слова «НЕТУ».

Нема до чого причепитися—причепись до граматики.

Це не до дмітрія а до рєдколегії. Всі тексти перед публікацією проходять вичитку та редакцію спеціальними людьми.

ну раз нету то нету, и ладно.

Спасибо, отличная статья

Да особого смысла нету как по мне. Джава быстро его по фичам догонит. На андроиде, да, котлин, пожалуй, лучший выбор.

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

особенно с учетом ее консервативности.

Ну релизы последнего года показали, что это уже не так.

Как слова «Джава» и «быстро» оказались рядом? :)

Пожалуй, единственная конструкция из всего списка, которую я использую почти каждый день: ... instanceof
За последние 5 лет написал 1 рекурсию. За всю жизнь штук 5 (в продакшн коде). В промышленном коде рекурсия — это скорее плохой стиль, нежели необходимость.

Статью следует назвать «Почему Д.Думанский еще не осилил программирование на Java. Yet.»

В нього свій успішний хайлоад стартап що працює на сінгл ноді дігітал оушену і використовує файли замість RDBMS, а у вас?

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

Хыхы, а сколько таких упоротых решений было навязано разными упоротыми архитектами

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

Хотите паттерн матчинг — Scala в вашем распоряжении.

«единственная конструкция из всего списка, которую я использую почти каждый день»
То есть вы не понимаетте ООП и не умеете им пользоваться, но при этом рассуждаете о Java? Зачем?

о есть вы не понимаетте ООП и не умеете им пользоваться, но при этом рассуждаете о Java? Зачем?

Лол. Просто лол.

Это тот же джентльмен, что пару лет назад рассказывал «СУБД не нужны» а потом таки взял postgresql ))) Опасен тем, что его могут прочесть неокрепшие умы ;)

Это тот самый, у которого объекты в фоне в JSON-формате на диск записывались?

Это тот самый, у которого объекты в фоне в JSON-формате на диск записывались?

И записуются до сих пор. Несколько десятков бизнесов больших и мелких успешно юзают и счастливы.

То что вы не осилили Java и реляционки, мы уже поняли. Мне вот интересно, какая будет следующая ваша статья. Вангую что-то вроде «Алгоритмы не нужны: как десяток больших и мелких бизнесов успешно юзали сортировку пузырьком».

То что вы не осилили Java и реляционки, мы уже поняли.

У меня такие комменты вызывают лишь улыбку. Видно, что разозлил школьника.

Дмитрий, будь мужиком! признавайся что ниасилил все вышеперечисленное и пишешь как можешь :) Тогда у людей вопросов не будет )

а потом таки взял postgresql

Postgres использовался и используется исключительно для бекапов. Попробуйте прочитать статью еще раз.

а вот это печально... хорошо что вам по собеседованиям ходить не приходиться ;) вы избежали больших расстройств )))

а вот это печально...

Печально это про Ваши комменты. Когда будут хоть какие-то аргументы, а не переходы на личности, буду рад выслушать Ваше против.

А при чому ООП до джави? Всі на джаві пишуть процедурний код, які проблеми?

Ой, точно не всі, Бугаєнко не пише процедурний. Але він останнім часом на рубі пересів.

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

Та ну, в щоденній розробці мене в 100 разів більше напрягає екосистема, а саме:

1. супер довгий редеплой/рестарт арр серверу та відсутність норм рішення для хотредеплоя зкоробки—на жребел нема грошей, шаманити с підхаченними jvm не хочу, про хотсвап через дебуг знаю але в нього купа обмежень.
2. відсутність норм реплу (не знаю що там в 11 прикрутили я ще на 8 сиджу, може вже і пофіксали)
3. як похідне від попереднього—репл який запускається всередині аппу і дає повний доступ до оточення, щоб можна було би зразу подивитися що там де, замінити-підхачити і тд, але без дебагу )))

Це зовсім не про мову але якби ці всі ніштяки були то девелопмент на жабі був би турбореактивним.

Чесно кажучи після року на RoR мене верне (буе) від жава-девелопмену, все сука так повільно, так довго, що ти просто постійно втрачаєш час на переключення контексту замість того щоб залишатися в щільному read eval print loop і не давати мізкам відволіктись. Розробка на джаві в поточній екосистемі—це суцільна мука в пеклі з бородатими чортами у светрах і неможвлиість зробити патерн матчинг це напевне останнє про що б я думав )))

супер довгий редеплой/рестарт арр серверу

В мене сервер стартує за півсекунди і з штмл і джс джарка важить 18мб. Так що це проблема точно не джави.

реплу

Что це?

все сука так повільно, так довго, що ти просто постійно втрачаєш час на переключення контексту замість того щоб залишатися в щільному read eval print loop

В мене такої проблеми взагалі нема. Можливо проблема у невірно підібраних інструментах для рішення задачі?

невірно підібраних інструментах

Ну, макбук 15го року з 8 гб рам напевне точно не дуже інструмент для жавадевелопменту, але альтернатив, нажаль, немає...

сервер стартує за півсекунди

Так у вас нетті всі діла а в мене і 80% котанів звідси спрінг бут і хібернейт.

Ну, макбук 15го року з 8 гб рам напевне точно не дуже інструмент для жавадевелопменту, але альтернатив, нажаль, немає...

Я мав на увазі всякі томкати, айбіем сфери =).

Так у вас нетті всі діла а в мене і 80% котанів звідси спрінг бут і хібернейт.

Ну зараз є купа легких альтернатив. Звичайно, що якщов вам треба 100к об’єктів заінджектити через рефлекшн, то це швидко ніяк не зробити.

REPL реализован в jdk 9

А, ясно. З 11-ки вже можна і звичайчий java клас виконувати без компіляції.

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

Насчет репла это да, но его таки выдали в 9ке, ура, товагищи. :)

Насчет рестарта апп сервера, что в вашем понимании — супердолгий?

что в вашем понимании — супердолгий

Більше 5 секунд.

И в чем проблема с тем, что сервер стартует 5-10 секунд? Ну то есть очевидно, что чем быстрее тем лучше, но почему эта проблема столь существенна?

Я кстати, тоже не понимаю. Мне кажется, это чтото хипстерское. Типа еси приложение сложнее 3 классов, то все, блади интирпрайз, «долго стартует». У нас старт приложения занимает в стойке около 40 секунд, и что дальше?

Я кстати, тоже не понимаю.

І не зрозумієте якщо ніколи не девелопили на PHP/Ruby/інших мовах с динамічною типізацією та інтерпретаторами.

ніколи не девелопили на PHP

Б-г миловал

Это да. Там же «старт приложения» выполнятеся при каждом request-е, поэтому в волшебном мире «PHP/Ruby/інших мовах с динамічною типізацією та інтерпретаторами» «пять секунд стартует» будет сильно хуже «старт приложения 40 секун» в java, хихикс.

Мені по барабану як там воно всередині працює аж поки я можу бачити свої зміни після натискання F5 а не рестарту сервера.

Ну так зачем тебе джава? Есть же замечательные PHP и Ruby

Дядь, шо за пред’яви? Я джава девелопер між іншим і хочу щоб мій воркфлоу не переривася ребутами сервера і підйомами спрінг контексту по 3 хвилини. На мому ноуті простий спрінг бут апп стартує мінімум хвилину. Для мене це довго, особливо коли те саме на rails не потребує рестарту взагалі. Коли можу користуюсь хотсвапом в дебазі, але в нього є відомі обмеження.

На JRebel грошей немає.

Якщо тобі подобається їсти кактус то це не значить що це подобається всім.

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

Я просто очень, очень сильно недоумеваю зачем вы берете джаву, пытаетесь работать с ней как с PHP и удивляетесь, что джава работает не как PHP. Точно так же автор топика берет джаву, пытается работать с ней как со скалой, напарывается на отсутствие паттерн матчинга и удивляется, что, ужас какой, джава это не скала. А еще в джаве нет деструкторов, как в C++, да и напрямую с памятью она как ассемблер работать не может, печаль-беда.

Может это вам стоит перестать есть кактус, перестать забивать гвозди паяльником и взять в руки молоток?

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

Ну і пиши собі, тільки справа в тому що інтеграційні тести на АРІ теж піднімають app сервер )))

Я просто очень, очень сильно недоумеваю зачем вы берете джаву, пытаетесь работать с ней как с PHP

Писанина рест арі та бекенду це неправильне застосування для джави?

Дядь не неси пургу.

Я не ем кактус.

Їж-їж, просто ти не в курсі ще )))

Писанина рест арі та бекенду це неправильне застосування для джави?

Писанина бекэнда на 90% покрывается юнит тестами. Судя по тому, что тебе нужно на каждый чих подымать сервак с интеграционными тестами, ты занимаешься апи для веба или для мобайла, где все сводится к crud-ам. И, да, Java — не самый лучший язык, когда тебе нужно 100500 крудов для веба или мобайла. Использовать джаву для такого это как раз есть кактус. Реально тот же руби подходит намного лучше. Не говоря уж о serverless солюшнах типа Cognito.

Я интеграционные тесты прогоняю в лучшем случае 2-3 раза в день и то делаю это обычно через дженкинс.

ты занимаешься апи для веба или для мобайла, где все сводится к crud-ам

лол ні

Использовать джаву для такого это как раз есть кактус

ок )))

Не говоря уж о serverless солюшнах типа Cognito.

ахахаха, у вас помилка в слові Lambda )))

Я интеграционные тесты прогоняю в лучшем случае 2-3 раза в день и то делаю это обычно через дженкинс.

)))
ок

Вопросов больше нє імєю!

Если разработка так сильно замедляется из за очень долгого редеплоя, то почему контора не может купить jrebel? Ну да 45 баксов в месяц на человека не дешево, но и стоимость времени разработчика серьезная.

Кстати насчёт свитча по классам — и хорошо, что их нет. Применяться он будет для выполнения каких либо действий в зависимости от подкласса, что означает — полиморфизм «вручную».

Не согласен. Во-первых — классы не всегда ваши. Во-вторых — полиморфизм не всегда хорошо и часто проще/быстрее/выгодней без.

Во-первых — классы не всегда ваши.

Используем Visitor — и получаем в плюсе статическую верификацию, что мы случайно не забыли какой-то из сабклассов добавить в case.

Во-вторых — полиморфизм не всегда хорошо и часто проще/быстрее/выгодней без.

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

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

Да любой кейс, где один-два-три класса выпадают из общего поведения в отдельных ветках логики. Реальный мир очень редко ложится идеально на ООП. В проектах это сплошь и рядом. Я думаю и у Вас в проекте такого полно. Просто поищите по instanceOf...

Да любой кейс, где один-два-три класса выпадают из общего поведения в отдельных ветках логики.

«Любой кейс» — это не пример

Я думаю и у Вас в проекте такого полно. Просто поищите по instanceOf...

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

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

У всех людей на руках 5 пальцев. Но есть люди с шестью пальцами. И тут, как ни крути, Вам прийдется подпипрать ифчиком. Это не говнокод. Просто нету ни совершенной модели ни совершенного мира. Это ок. Зачем с этим бороться?

А зачем вам знать сколько пальцев на его руке? Вы когда авто ведёте тоже руками колёса крутите? Вам достаточно знать может ли человек что-то сделать (принять инстанс такого-то контракта в метод) и отдать команду это сделать. Вы в любом случае получите invokevirtual просто потому что это java так что производительность не может быть оправданием к написанию такого говноifо-кода

А зачем вам знать сколько пальцев на его руке?

Потому что проект продает перчатки?

Вы в любом случае получите invokevirtual просто потому что это java

После компиляции — да. В райнтайме — it depends.

Потому что проект продает перчатки?

Предложите ему ваши перчатки на выбор. Он знает сколько именно у него пальцев, левых и правых рук — он и выберет. Может он вообще не на себя покупает? Тогда вы отсеете потенциально годный продукт по кол-ву пальцев и проект не получит продажу.

Да, любой кейс с немочной моделью, тупыми data-envelop’ами и процедурами вместо классов/объектов.
Только если вам удобен/нужен для производительности (бенчмарки есть?) такой код — зачем пользовать java? Пользуйте С и будет вам щастя.
А то при одном годном решении (не пользовать апп-сервера и сервлет-контейнеры, а выучить Netty) такая куча ереси из разряда «Open-Closed? Не, не слышал» c if’ами и instanceof’ами

То есть у вас в коде нету instanceof? Или может быть проще — вы не пишите код?

бенчмарки есть?

Есть

нету instanceof? Или может быть проще — вы не пишите код?

В Java коде уже давно нет. В Scala есть значительно хуже — match/case но там это фреймворком обусловлено типизированой версии которого в проде ещё долго не будет.

Полиморфизм в принципе сложнее, чем свич по классам или инстансоф, потому что для человеческого восприятия менее очевиден.

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

Полиморфизм в принципе сложнее, чем свич по классам или инстансоф, потому что для человеческого восприятия менее очевиден.

Интересно, с какой стороны он сложнее? Полиморфизм работает на сокрытие деталей реализации, позволяя сконцентрироваться на том, что важно в данном конкретном коде.

Полиморфизм в принципе сложнее, чем свич по классам или инстансоф, потому что для человеческого восприятия менее очевиден.

нет. Просто нет. Менее привычен, может быть. Но это индивидуальные особенности. Ничего с обще-человеческим восприятием здесь не связано. Просто кого-то прогнули писать процедуры.

Java есть не только на бэкенде. И даже не только на десктопе. Есть мобильные девайсы и IoT, например. В UI, когда тебе в колбэк приходит объект базового типа view и есть несколько действий которые надо произвести. Или List — когда получаешь список элементов в ListView и надо перебрать и и что то с ними сделать в зависимости от типа(Например выбрать свои View привести к нужному типу и проигнорить системные). Тут вообще ни полиморфизм не впихнешь никак ни визитор(Ну или переписывать половину UI библиотеки надо :) ).
ПС. Здаровки :)

Привет :) К сожалению, ничего не могу сказать о том, что ты написал, т. к. это не моя область. В обычной enterprise/web-разработке с новыми библиотеками мне такие ситуации практически не встречались. Единственное, что могу вспомнить сейчас — equals(Object), но это тоже legacy. Собственно, поэтому я и просил Дмитрия привести какие-то конкретные примеры, поскольку его проект, наверное, ближе к тому, что ты описал, чем к тому, чем занимаюсь я.

Тем не менее, вопрос остается — нужно ли добавлять в язык возможности, которые поощряют грязный код? Моё мнение обратное — такие операции нужно затруднить как можно сильнее, чтобы человеку элементарно легче было писать правильный ООП-код, чем «процидурки на джаве».

В обычной enterprise/web-разработке с новыми библиотеками мне такие ситуации практически не встречались.

github.com/...​earch?l=Java&q=instanceof не благодарите.

Посмотрел пару первых классов, ну что сказать, аргумент остается — эта конструкция используется в основном в говнокоде.

В первом же классе: @SuppressWarnings("unchecked")

Nice! Давайте еще до кучи предложим unchecked-ворринги убрать, чтобы еще легче было писать такой код ;)

Посмотрел пару первых классов, ну что сказать, аргумент остается — эта конструкция используется в основном в говнокоде.

Может покажите свои коммиты или свой опен-сорс проект? Чтобы мы могли понять «как надо»?

Это в любом случае лучше, чем «сперва обосри».

Помилуйте, вы ошибаетесь. Я никого не обсирал. Напротив, я испытываю глубокое уважение и к программистам спринга, и к вам, потому что успешное развитие opensource-проекта требует больших усилий, управленческих умений и дисциплины. Но это не отменяет того факта, что данные конкретные примеры кода могли бы быть лучше.

Посмотрел пару первых классов, ну что сказать, аргумент остается — эта конструкция используется в основном в говнокоде.

Спринг — говнокод?

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

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

Ну, вообще спринг считается крайне чистым кодом.

Источник, плз. Вы уже не первый раз делаете ничем не подкрепленные заявления.

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

«Ооо!.. Етить твою мать, профессор! Иди сюда, выпей с нами!» ©

Источник, плз.

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

спринг считается крайне чистым кодом

ну как,
как у вас такое в голове умещается когда вы же парой комментов выше пишете:

посмотрите код спринга, там инстансофами весь код пересыпан

что явно говорит о Open-Closed violation а значит никакого Clean там и в помине нет.
Ладно, назвать его оправданым, ладно авторитетным от людей с пхд — кстати, тоже упоминаний об этом нигде не встречал. Но называть его чистым когда в индустрии уже устоялся этот термин? Как?

как у вас такое в голове умещается

Если у вас чтото в голове не умещается, то это исключительно проблема вашей головы.
habr.com/...​ompany/jugru/blog/425961
Не знаю, поможет ли чтение. Уровень доу-эксперта у вас такой, что может препятствовать восприятию информации.

Open-Closed violation

Употребление умных слов из вики, к сожалению, ни смысла ни веса вашим постам не добавляют. И опен-клозед принцип к инстансофу имеет отношение примерно такое же, как банан к розетке, это так, для справки.

За роки роботи до дрібниць якось звикається і компенсується лібами. Взагалі, в кожній мові є свої «незручності».

До того, чого дійсно не вистачає:
— корутини (один проект спеціально частково на котлін переписували із-за них) . CompletableFuture — круто, але до корутин ще далеко.
— System.setProperty — вбиває всі спроби ізоляції параметрів, які там ставляться.

Джава всё ещё не торт потому, что она не скала, и даже не котлин. И скорее всего, большинство самых мощных фич (Макросы поверх AST языка, quasiquoutes, apply/unapply + pattern matching, Higher kinds, implicits/type classes, ассоциативность операторов и возможность помещать карлючки в названиях методов для создания dsl, и ещё многие и многие другие фичи + мощная система типов), которые есть в функциональных и околофункциональных языках останутся за бортом джавы, потому что «это делает код непрозрачным» (и в правду, если добавить сложности из разряда изменяемое состояние во все поля, будет треш). Но, определённо часть этих фич потихоньку будет переползать в другие языки. Вон в C# попробовали сделать подобие паттерн матчинга, в джаве люди начали использовать optional, а котлин, судя по всему, вобрал много фич из скалы (для которой джет брейнс делают самый лучший плагин для IDE).
Но судя по тому, сколько злобы было со стороны джавистов при в ведении var, синтаксический сахар продвинутого уровня будет встречать ещё большее сопротивление.

сколько злобы было со стороны джавистов при в ведении var, синтаксический сахар

А интересно, почему это вдруг?

Мотивированно тем, что если вы получаете объект не по new, а например через SomeFactory.fabricate(...) или же как результат работы метода, то T baz = foo.bar «выглядит понятнее» чем var baz = foo.bar .(в итоге, по мнению агрящихся с варами получается бестолковый непонятный код) Такой аргумент очень часто видел, но очень он мне не понятен, какие могут быть проблемы если любая IDE синферирует вам тип по щелчку хоткея.

Я перешел на var и критики правы. Если var не возле new T(), то код читается хуже и на него третится больше времени.

Хотел бы выяснить для себя (у нас в команде пишут код где типы выставляются в основном в сигнатурах функций, внутри кода типы ставятся только в тех местах где компилятор их вывести не может), на что именно тратится время?

На чтение. Код вроде:

var newTileTemplate = JsonParser.parseTileTemplate(tileTemplateString);
var existingTileTemplateIndex = deviceTiles.getTileTemplateIndexByIdOrThrow(newTileTemplate.id);
var existingTileTemplate = deviceTiles.templates[existingTileTemplateIndex];

Труднее читать без информации о типе

Такое трудно читать хоть с var хоть с типами.

На чтение чужого кода, внезапно. Не в иде. Мерж реквесты ревьюите чужие?

если любая IDE синферирует вам тип 

Я вот сразу вижу человека, который не занимается ревью мерж реквестов.

А я занимаюсь. И именно поэтому я люто против вар.

Ну такое... Если в коде разобраться без типов нереально, то, видимо, он плохой

Читал где-то мысль, что var полезен еще и в том смысле, что заставляет девелопера лучше думать об имени переменной, которое по определению более конкретно, чем тип этой переменной (и, соответственно, более полезно при чтении)

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

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

мне в день надо просмотреть десятки и сотни ченжей.

Интересно, что у вас за работа такая, где в день сотни изменений надо просматривать (это как минимум 1 изменение каждые пять минут)?

Второй, более важный вопрос — какой именно аспект просматриваемого кода позволяет вам оценить явное указание типа?

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

Что мешает заниматся мёрджем внутри IDE?

T baz = foo.bar

А еще, увы, примеры не всегда сводятся к фу бар.
Видя вполне типичный джава-стайл код типа:

var component = componentHolderCommonPlatfromConfigurableFactory()
       .getComponentHolderPlatformDependingOn(settings)
       .getComponentHolder(anotherSettins, someObj, null, true)
       .getComponent();
мне, блин, офигительно интересно что же там в этом сраном var инкапсулировалось.
Видя вполне типичный джава-стайл код типа:

Это типичный trainwreck.

Ну уже поздно ругать var, все покатилось к чертям еще на введении default в интерфейсы :)

все покатилось к чертям еще на введении default

Не согласен категорически.
Default офигительно усилило концепцию интерфейсов.
Лично я очень сильно жду private default.

Так private в интерфейсах есть еще с Java 9

Нету:
Создать объект класса из текстовой переменной. Так же использовать метод класса.
Хотелось бы писать:
Object ob = new «MyClass»;
ob."read"();

Создать объект класса из текстовой переменной.

Есть же — Class.forName(className).newInstance();

Ага.
Throws: IllegalAccessException, InstantiationException, ExceptionInInitializerError, SecurityException

и все чекед

Так потому что создавать объект по классу из строки — это крайне error-prone операция, не? А то хотим и код строками писать, и чтобы типобезопасно.

крайне error-prone операция, не?

Абсолютно согласен. Так я и не поддерживал изначальную идею комментатора про "className".newInstance(), я просто напомнил, что

forName(className).newInstance()

И так весьма нелегкая штука.

А что вам не нравится в сегодняшней Java?

то, что она до сих пор существует

угу. хнык-хнык
пришлось пойти сеньором на плюсах

то, что она до сих пор существует

С высокой вероятностью она переживет всех нас, так что можно начинать страдать :)

В моих хотелках — это value types, extension methods, kill checked exceptions.
1. value types позволили бы джаве стать отличным языком для геймдева, а без них — приходится оптимизировать векторные операции чтобы не грузить ГЦ (throughput vs gc pauses). Со «структами» этого не пришлось бы делать совсем.
2. extension methods — с помощью них можно было бы легко расширять АПИ. Например, стримы — были бы лишь одним из расширений коллекций. И мы не ждали бы следующих версий джавы, а просто писали/использовали сторонние расширения АПИ.
3. checked exceptions — самая раздражающая «фича», заставляющая хендлить ситуацию не там где её удобно/логично похендлить, а в древнейшем из стилей — чекать сразу после вызова.

Да, это всё заставляет смотреть в сторону C#.

checked exceptions бесит а особенно внутри лямбды

1. value types позволили бы джаве стать отличным языком для геймдева, а без них — приходится оптимизировать векторные операции чтобы не грузить ГЦ (throughput vs gc pauses). Со «структами» этого не пришлось бы делать совсем.

Наличие структур особо не спасало c#. Для векторных операций всегда юзали unmanaged код. Вот с#7.* туда подобавляли крутых фич типа stackalloc и работа с unmanaged буферами в managed коде, полная ref семантика для value types. Все это позволило писать managed код как он был 20 лет, но с куда меньшей нагрузкой на gc. Это уже недосягаемые вершины для Jvm стекa в ближайший перспективе.

Да, вот value types на границах приложения очень сильно не хватает.

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

  1. Currying — очень помогло бы снизить вложенность кода и сложность лямбд. Было:
    List<Product> fetchProducts(List<Integer> ids, int timeout) {
    	Function<Integer, Product> fetcher = id -> 
    		fetchProduct(timeout, id);
    	return ids.stream().map(fetcher).collect(..);
    }
    
    Product fetchProduct(int timeout, Integer id) {
    	return ..;
    }
    
    Стало:
    List<Product> fetchProducts(List<Integer> ids, int timeout) {
    	return ids.stream().map(fetchProduct(timeout)).collect(..);
    }
    
    Product fetchProduct(int timeout, Integer id) {
    	return ..;
    }
    
  2. Pattern matching (тот, который настоящий) — когда требуется простое ветвление, функции бы стали гораздо нагляднее, было бы гораздо меньше ветвлений и вложений.
    Было:
    ProductModel fetchProduct(..) {
    	Response r = rest.call(..);
    	switch(r.statusCode) {
    	case FOUND: return new ValidModel(r.getBody());
    	case NOT_FOUND: return new NotFoundModel();
    	case SERVER_ERROR: return new ErrorModel()
    	}
    }
    
    Стало:
    ProductModel fetchProduct(..) {
    	return handleResponse(rest.call(..));
    }
    
    handleResponse Response(FOUND, body) = new ValidModel(body)
    handleResponse Response(NOT_FOUND, _) = new NotFoundModel()
    handleResponse Response(SERVER_ERROR, _) = new ErrorModel()
    
  3. Metaprogramming — даже если не макросы как в лиспе (что было бы сложно из-за гораздо более сложной синтаксической структуры), то хотя бы на уровне Groovy. Достаточно бы было даже такого рудиментарного механизма, как дополнительный динамический scope в лямдах (как owner в groovy).
    Было:
    RatpackServer.start(server -> server 
         .handlers(chain -> chain
           .get(ctx -> ctx.render("Hello World!"))     
         )
    
    Стало:
    ratpack {
      handlers {
        get {
          render "Hello world!"
        }
      }
    }
    
  4. Tail recursion — без нее эффективно использовать рекурсию невозможно, что делает программы гораздо менее выразительными.
  5. Переопределяемые операторы — опять же, для многих абстракций операторы могли бы иметь свой смысл (например, объединение списка через +). Сюда же можно добавить возможность вызывать функцию инфиксно:
    list3 = list1 `join` list2
    

  6. Type classes (из Haskell) — долго объяснять, что это и как оно работает, но оно бы заменило наследование в 95% случаев, избавив нас от тяжелых проблем наследования (сложность тестирования, высокая связность и т.п.)
  7. Улучшенный type inference — простейший пример, который до сих пор не решен джавой:
    long x() { return 10; }
    float x() { return 12.0; }
    long y() { return 15 + x(); }
    
  8. Reifiable generics — в ту же кассу, что и type inference. Type erasure вызывает кучу всем известных проблем и геморроя.

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

С другой стороны, общий уровень Java-программистов, к сожалению, таков, что вред может сильно перевесить преимущества, а все вышеописанные штуки решаются в той или иной мере либо более многословным кодом, либо введением дополнительных абстракций (читай — еще более многословным кодом).

Камон, половина этих проблем решается сторонними библиотеками, вторая половина — лишь небольшой синтаксический сахар.

Все решается. Но речь про удобство при каждодневном программировании.

Pattern matching (тот, который настоящий)

Это уже будет в 12-й версии — openjdk.java.net/jeps/325

Tail recursion

За последние 5 лет написал 1 рекурсию. За всю жизнь штук 5 (в продакшн коде). В промышленном коде рекурсия — это скорее плохой стиль, нежели необходимость. Так как это потенциальная угроза стабильности системы.

За последние 5 лет написал 1 рекурсию. За всю жизнь штук 5 (в продакшн коде).

Не задумывались, почему?

Не задумывались, почему?

Рекурсии трудно читать/понимать и почти всегда рекурсии можно избежать/заменить без какого-либо оверхеда.

Рекурсии трудно читать/понимать

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

Вот это да, а мужики-то не знают.

Тогда о чем речь? С большой вероятностью хвостовой рекурсии в джаве не будет и ничего плохого в этом нет, так надо это почти никому.

С большой вероятностью хвостовой рекурсии в джаве не будет

Ну так мы ж тут обсуждаем, что неплохо было бы иметь? Кстати, я бы не был так самоуверен — это гораздо менее breaking change, чем некоторые из вами описанных синтаксические улучшения. И в CLR, допустим, поддержка tail call optimization есть.

так надо это почти никому

Ну мне надо, например (по крайней мере, было бы неплохо). Ок, 90% Java-программистов это не надо. Так им и clean code не надо, что тут думать — пилить надо.

Ну так мы ж тут обсуждаем, что неплохо было бы иметь?

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

Ну так то улучшение, которое вы описали — это просто следствие type erasure. Зачем хотеть какого-то new ArrayList<>(array), когда можно хотеть proper reified generics? Но вот лично для меня такой синтаксис мало того что кажется слишком специфическим, так он еще и двусмысленный. Чего вы хотите им добиться? Чтобы за списком стоял этот массив? Чтобы он скопировался в новый список? Для меня это неоднозначно.

его вы хотите им добиться? Чтобы за списком стоял этот массив? Чтобы он скопировался в новый список? Для меня это неоднозначно.

Длля этого есть джавадока.

„A comment is a failure to express yourself in code. If you fail, then write a comment; but try not to fail.” © Анклбоб

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

В чем «потенциальная угроза стабильности системы» и в чем плохой стиль?

Легкость введения в СтекОверфловЕксепшн.

Ну так null’ы ваши в джаве тоже легко могут довести систему до состояния сосиски.

Нуллы и НПЕ в частности — это прекрасно. Потому что НПЕ с вероятностью 99,99% указывает на явную ошибку программиста в логике.
Если нуллы довели вашу систему до состояния сосиски — могу вас только поздравить :) А у нас НПЕ возникают раз в квартал, и указывают на специфическую проблему в логике, после чего мы ее исправляем.

То же самое можно сказать про рекурсию или любой другой источник проблем

Вопрос, как всегда, в умении владения инструментом ;)

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

Ну о nullability тоже нужно всегда думать. О mutability нужно всегда думать. О много чем нужно думать при написании кода. Почему вы выделяете именно рекурсию?

Потому что нуллабл ни мутабл не являются антипаттернами. А рекурсия им является. Потому что нулл описывает конкретное состояние системы, как и мутабл. А рекурсия описывает бесконечность.

Это вы решили, что рекурсия является антипаттерном? Есть ссылки на источники дровишек? Про «нуллабл не является антипаттерном» — это не антипаттерн (это вообще к паттернам отношения не имеет), это некорректная имплементация option type (сравните, например, с Optional, который представляет собой ту же абстракцию, но в безопасном виде).

Вот в ваших сентенциях точно каша и непонимание того, о чем вы говорите

представляете, что будет с вашим мозгом, если вам еще и про удаление памяти думать придется?
му а ха ха ха

Для справки: в том то и плюс именно хвостовой рекурсии — она stack safe.

Это уже будет в 12-й версии — openjdk.java.net/jeps/325

Извините, но это какие-то козьи какашки. Вот немного информации, что такое настоящий pattern matching: www.haskell.org/tutorial/patterns.html www.futurelearn.com/...​ing-haskell/0/steps/27226

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

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

Что вы конкретно под этим понимаете? Возможность запускать ранее скомпилированный код на новых версиях Java? Ну так в восьмой добавили лямбды и invokedynamic, и ничего, никто не обиделся. Имеете в виду возможность компилировать legacy код новыми компиляторами? Ну так это, по идее, решается правильным -source, нет?

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

пожалейте сыроедов, не осиливших обычные лямбды со стримами)

Сам удивился, когда реально таковых нашел)

Увы, учитывая последний абзац и в целом реалии enterprise-разработки, проще пойти другим путем и «просто фигачить код» (т.е. идти путем внесения дополнительных абстракций и написания более многословного кода).

Многословность != плохо.
Многословность == детальность и очевидность.

Я например, не хочу чтобы стройная и очевидная джава превратилась в набор синтаксических заклинаний.

Разницу между expressiveness и boilerplate объяснять, надеюсь, не нужно? Под «многословностью» здесь понимаю именно boilerplate. Многословность в понимании Literate programming — изящная концепция

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

А рекурсии вообще комментировать не хочу. За всю жизнь написал аж 1 или 2 рекурсии, на этапе изучения алгоритмов сортировки.

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

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

Ну а я вижу отсутствие у вас какого-либо интереса к написанному, лишь какие-то популистические фразы типа «здравый смысл и рекурсия» и «джава как стиль ооп» (wut?) без каких-либо подтверждений и разумных разъяснений.

популистические фразы типа «здравый смысл и рекурсия» и "джава как стиль ооп"

Они вполне имеют смысл. Но не для тех, кто предлагает рекурсию в качестве нормального решения, это очевидно.

Возвращайтесь, когда разберетесь хотя бы еще с парой ЯП с человеческой реализацией функциональной парадигмы (можете взять F# или Scala, если западло Haskell изучать) и когда научитесь внимательно читать (см. внимательно пункт про tail call optimization).

Возвращайтесь

Спасибо, мне и здесь хорошо

когда разберетесь хотя бы еще с парой ЯП

Хочу вас разочаровать, я люблю работу работать, а не заниматься изучением ненужных на практике функциональных брейнфаков, потому что анонимус в интернетах так сказал.

хотя бы на уровне Groovy

А вот кстати. Мне, как совершенному дилетанту в JVM мире, после поверхностного знакомства с Groovy было совершенно непонятно, почему этот язык остался нишевым.

Стоит признать, что он хоть и нишевый, но в свои области вписывается идеально. Это DSL (примеры — gradle, ratpack, свои DSL тоже пишутся достаточно легко), юнит-тесты (spock, cucumber), и т.п. В качестве основного языка он непопулярен потому что большинству Java-разработчиков это неинтересно (почитайте хоты бы комменты в этой теме), а те, которым это интересно, видят гораздо больший потенциал в Scala и Kotlin. По крайней мере, мне так кажется.

те, которым это интересно, видят гораздо больший потенциал в Scala и Kotlin

Спасибо, любопытное мнение!

Вместе с тем, слышал от некоторых матёрых джавистов мнение, что они никогда бы не притащили Kotlin в back-end — если правильно понял, потому, что Kotlin плохо стыкуется со Spring экосистемой. Заранее прошу прощения, если чего переврал.

Что касается Scala — то она ИМХО черевата холиварами между функциональными пуристами, пишущих на Scalaz с закрытыми глазами, и более умеренными фракциями, которые не видят крамолы в грамотном смешивании ФП и ООП :)

В сегодняшней Java не нравится сама Java. Даже замыкания не могут нормально сделать. Все это и намного больше уже давно есть в Groovy. Пользуйтесь Groovy и сохраните себе нервы в ожиданиях реализации «новой» суперфичи в Java.

Але треба тягнути з собою його runtime.

Мои нервы, например, в полном порядке. Вас бесит джава? Так не пишите на ней. Только вот груви не взлетел.

Меня не бесит, судя по посту ТС — да.

Только вот груви не взлетел.

Ну так ничего не взлетело, кроме большой четверки. Но это абсолютно не мешает на нем писать.

Меня не бесит, судя по посту ТС — да.

-

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

Большая четверка? Можно в студию!
Неужели это Java, JS, PHP, Python?

Где-то так. Например здесь dou.ua/...​ry-report-june-july-2018. Я бы вместо Python поставил C#.

Но вот больше всего мне хочется изкоробочных ивентов.
Чего-то типа
fireAsync("eventName");
...
awaitFor("eventName").thenDo(() -> {....});
listenFor("eventName").withListener(() -> {...});

И еще чтобы такое же но с пейлоадами. И чтобы прямо в ждк. import java.events.* и го го го.

Мне кажется, это из разряда dependency injection из коробки — там слишком много внутренних решений, чтобы быть полезным всем разработчикам. Добавили в семерке Fork/Join — много ли людей его реально использует?

dependency injection из коробки

Кстати тоже было бы неплохо. Гдето даже есть JSR для добавлния поддержки @Inject прямо в SE.
Мне это кажется здравой идеей, поскольку позволяет не тянуть спринг в мелкие пет проекты.

Добавили в семерке Fork/Join — много ли людей его реально использует?

Без понятия, но мне его апи показалось просто неудобным.

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

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

Да. Но хочется стандарта, а не import noname.mylib.*

Да. Но хочется стандарта, а не import noname.mylib.*

Стандарт — это спецификация JVM или JEE. А спринг это просто фреймворк.

В данном случае имел в виду стандарт == часть JDK.

И снова таки — гусь отлично обрабатывает javax.inject.* а это уже — стандарт. Да, в SE притягиваются зависимостью, но от этого стандартом быть не перестают.

Гусь и иже с ними

позволяет не тянуть спринг в мелкие пет проекты

Без понятия, что такое гусь.

Да, на его родине его называют джуйс, но в наших то широтах он под этим именем чаще всего встречается.

Да, на его родине его называют джуйс

гитхаб > Guice (pronounced ’juice’)

Гусь

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

Единственное, что я нашел, это инструмент по парсингу статей в вебе, Goose.

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

к вопросу List<> to []
Еще бы добавить поддержку Iterable в массивы, тогда все входные параметры станут Iterable и это бы решило массу проблем с преобразованиями.

А, ну и все еще нет ведь указателей на функции...

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

Неее, в этом как раз фишка массивов. Вот пару дополнительных методов вроде copy(), contains() не помешало бы.

А, ну и все еще нет ведь указателей на функции...

Есть Function, предикаты, не очень удобно, но частично есть.

Function, предикаты, не очень удобно

А как по мне они полностью перекрывают все потребности.
Более того, играться с указателями на фукнции — ИМХО, уход в сторону от ООП. Method reference в лямбде не в счет, т.к. просто сахар для функциональных интерфейсов.

Хочу Integer.isInteger(String s) и ему подобных.

Пф... самая главная проблема это отсутсвие нормального const модификатора как в С++. В итоге пишутся костыли из серии Collections.unmodifiableList() которые при этом не гаратируют иммутабельности самих объектов.

А что вам не нравится в сегодняшней Java?

Если уж совсем капризничать, то
— вырезание JavaFX из JDK и переезд на раздельные продукты OpenJDK + OpenJFX.
— отсутствие многих утильных метдов: Collection.isNotEmpty(), Optional.isNotPresent(), Optional.orThrow(), String.isNotEmpty() и прочих, тысячи их. Часто хочется мутабл опшнал.
— отсутствие Currency API, изза чего приходится использовать крайне _удобный_ BigDecimal
— отсутствие изкоробочной реализации ивентов прямо в стенделоун SE.

Да, хорошие поинты.

— вырезание JavaFX из JDK и переезд на раздельные продукты OpenJDK + OpenJFX.

Это, кстати, считаю абсолютно правильным.

— отсутствие многих утильных метдов: Collection.isNotEmpty(), Optional.isNotPresent(), Optional.orThrow(), String.isNotEmpty() и прочих, тысячи их. Часто хочется мутабл опшнал.

Небольшие подвижки есть. Например, класс Objects. Optional так же понемногу расширяют.

Это, кстати, считаю абсолютно правильным.

Почему?
Официальные комментарии я прочитал все, я слежу за этой темой, но несмотря на огромный прогресс команды OpenJFX, разделение на два продукта — это большой минус для платформы.
Увы, у меня еще не было времени хорошо разобраться с модульной системой, и тем, как оно будет работать, но пока все предложения устанавливать OpenJFX отдельно похожи больше на костыли. Основной минус — что для того, чтобы запустилось приложение JavaFX-компонентами, теперь недостаточно просто «скачать джаву».

Почему?

По той же причине по какой больше нету JEE. Джава стала большим монолитом, который стало очень дорого поддерживать и изменять. И было принято единственное правильное решение — модульность. Ну и для этой самой модульности естественно нужно отсечь все, что пользуется малым спросом и мешает.

— отсутствие Currency API, изза чего приходится использовать крайне _удобный_ BigDecimal

так вот же:
javamoney.github.io

Правда, пока это не часть jdk

Спасибо, надо будет глянуть.

Правда, пока это не часть jdk

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

Optional.isNotPresent()

когда это вообще может понадобится?

отсутствие изкоробочной реализации ивентов прямо в стенделоун SE

а потом ивенты станут distributed и начнут выходить за рамки одной JVM и такая реализачия станет очередным JUL

когда это вообще может понадобится?

При написании кода, например. На джаве. Понимаю, код писать это не постики на доу фигачить :)

а потом ивенты станут distributed

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

А вот просто ивенты пригодились бы.

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

А вот просто ивенты пригодились бы.

Попробуйте Visual Basic, там всё как вы любите — ивенты из коробки, нет излишней сложности (и не предвидится) :D

Visual Basic, там всё как вы любите

Тролль из вас, надо признать, так себе

При написании кода, например. На джаве.

Достаточно map. По хорошему то что один раз до Optional lift’или дальше до границы приложения из него не выходит.

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

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

Что за глупость, если человек не использует инструмент, то он его не осилил? Удивительно, что Вы с такой логикой осилили программирование. Откройте любой топовый опен-сорс проект и посмотрите как «много» там опшинала.

Почему не использует? Он же явно пишет о том что пользует опшналы только хочет их использовать просто как врапперы, ref-envelope’ы. Да ещё и mutable.

любой

я достаточно часто захожу внутьрь Play framework’а — да, не спринг, да и вряд ли им станет, но и безизвестной поделкой на коленке его назвать нельзя. Так там достаточно правильного использования опшнала. Собственно, везде где null, теоретически, может появится.

Что за глупость

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

не осилили концепт опшнала и композиции

Какой нафиг концепт?! Вот блин хипстота, любой класс им уже «концепт». Парадигма еще скажите. У стринга и инта тоже есть концепт? Ага, и у лямдбы, концепт. Особый, высокодуховный концепт. Вон тут в треде ваш коллега любит рекурсии писать, «концепты» простейшых классов с ним обсудите.

Вот концепт:
One of the most interesting features that Java 8 introduces to the language is the new Optional class. The main issue this class is intended to tackle is the infamous NullPointerException that every Java programmer knows only too well.
Интернет, первая страница гугла.

A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
Java SE 8 API, не знаю, читали ли.

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

Since 1.8.
Джавадоку глянуть религия не позволяет?

isEmpty
public boolean isEmpty()
If a value is not present, returns true, otherwise false.
Returns:
true if a value is not present, otherwise false
Since:
11

Проблема-то как раз в том, что мне джавадоку религия смотреть позволяет, а вам — увы, нет.

Optional.orThrow()
Optional.orElseThrow()

Я кажется написал не orElseThrow(), a orThrow(), без елс, да? Не заметили? orThrow() - это идеологическая замена .get(), не требует саплаера ексепшна как аргумента, но семантически подразумевает выброс НПЕ, в отличии от гета, который ничего не подразумевает. Я понимаю, что за дискуссиями об апи вы не следите, и о предложении депрекейтнуть гет() вы не слышали, бывает.

Простите, что?

Прощаю.
Теперь ответ на вопрос «што» — нужно это вот зачем — бывают кейсы, когда в объекте как поле содержится транзиент нот файнал нулабл объект, который может быть нулл, а может нет, и при этом с ним идет интенсивная работа, при этом его можно засетить, а можно обнулить, и это часть бизнес логики. В таком случае обилие иф ( обж == нулл ) начинает весьма надоедать и хочется иметь враппер с утильными методами, наподобие опшнала, только мутабл. чтобы ифПрезент(консьюмер) и ифНотПрезент(раннабл), и так далее, при этом можно было враппер.нуллифай() или враппер.сет(ньюОбж), или враппер.сетИфЕмпти(ньюОбж) и так далее.
Доступно?

Optional.of делает именно это и многими за это критикуется.

Вы или невнимательно читаете, или совершенно не поняли суть предлагаемого .orThrow(). Optional.of это создание опшнала, оно вне скопа данного обсуждения.
Речь же идет за использование уже существующего опшнала, когда вам уже пришел опшнал. Многие (я в том числе), видят недостаток в семантике метода .get(), потому что на самом деле он выполняет функцию .orThrow(), а .get() же максимум должен возвращать значение или нулл, оставляя обработку нулла на ответственность разработчика. Поведением «велью или ексепшн» должен обладать .orThrow().

Тогда может стоит для этого и написать свою кастомную обертку?

Для своих пет-проектов у меня такая уже давно есть. И ее можно скопировать и куданибудь в рабочий проект. Но чем больше стандартных решений — тем лучше.

Зачем бедный опшинал насиловать.

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

Гослинг жмакает F5, доу помогает ему.

Все по делу, но лично мне эти недостатки мало мешают. Кроме того, почти в каждом проекте есть своя пачка утилей, в довесок к апач коммонс.

А паттерн матчинг и свич по классам да, но я думаю что их быстро завезут.

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

в довесок к апач коммонс.

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

Значит, мало использовали коммонс :)

много подобавлялось статических методов на любой вкус.

Много, да не очень, и имхо не на любой.

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

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

На мелочи обращаете внимание, есть проблемы по важней.

Хотя-бы остосутвие асинхронности:
а) в синтаксисе
б) в стандртной библиотеке (HttpClient 9й джавы не в счет)

На мелочи обращаете внимание

Ну когда код пишется каждый день, то это не такая уже и мелочь.

Хотя-бы остосутвие асинхронности:
а) в синтаксисе

Есть библиотеки, фреймворки, которы давно решили эту проблему netty, akka, spring-webflux. Вполне норм там все с синтаксисом. Может не супер лаконично, но приемлемо.

б) в стандртной библиотеке

Тут сложнее. Сами знаете почему.

Когда я говорю о синтаксисе, я имею ввиду полноценные await, которые даже в JS завезли, во все барузеры, а не колбеки или еще какие пляски.

Только Play 2 решает данную задачу, но использовать ее стремно.

Вроде как обещают сделать легковесные треды (fibers) из project Loom. Не совсем в тему ответ, но думаю, что это задел на async/await

а чем стрёмно то? Давно уже в проде, не первый проект написан и уж что-то но Play так точно всё тортее и тортее

Уточняйте, что вы имеено про асинхронный веб.
j.u.c.CompletableFuture дает набор асинхронностей прям с оверкилом, поэтому я не сразу понял, какой асинхронности вам не хватает.

Знаю, использовал, но опять таки, нехватает нормального await, и поддержки стандартной библиотекой :(

Асинхронно ходить в реляционную базу. Именно чтоб стандартно, а не либами на коленке что не поддерживаются годами.

Асинхронно ходить в реляционную базу

Полезность трудно переоценить, спору нет. Я не изучал этот вопрос, но мне кажется тут вопрос скорее к разработчикам больших реляционных субд. Накидать спеку для типа реактив ждбс вообще не вопрос — проблема в том, как большие вендоры будут ее реализовывать коннекторами, и будут ли вообще.

У вендоров это как раз таки давно завезли. Иначе не было бы водможности делать что-то такое или такое. Просто в Java многие ждбц-хибернейтщики привыкли блокировать на пустом месте. Коллбэки им, видите ли, не удобны, с фьючерами только с восьмёрки начали учиться работать, даже по http большинство ходит через блокирующий url-connection хотя давно есть Netty-based AsyncHttpClient.

Это вам в скалу с akka-http и фьючерами. Если фьючеры не нравятся, берите монаду IO. ScalaZ -версия ZIO может использоваться прямо в джаве без извращений.

Підписатись на коментарі