Взгляд в прошлое, настоящее и будущее Java
Это прекрасное время, чтобы опубликовать это — прямо в выпуске Java 19. Да, еще одна статья мой язык лучше. Нет, не хотел писать. Но иногда плохая проекция людей берет надо мной верх. В данном случае статья начиналась как комментарий, а в итоге я решил превратить ее в статью. Это было усилено этим постом, который в основном жалуется на Quarkus (несколько несправедливо, если я могу добавить).
Первая статья по большей части бред и устаревший кликбейт. Я резюмирую это для вас в следующих утверждениях:
- Геттеры/сеттеры
- Отсутствует перегрузка оператора специально для
[]
для коллекций и+
для чего угодно. - Проверенные исключения
- Управление зависимостями
Во второй статье есть жалобы, которые больше связаны с Jakarta EE и общей эстетикой программиста в JVM. В частности, использование аннотаций для проверки и подобных утверждений. Это гораздо более информативная статья, но в ней есть пара недостатков, о которых я расскажу ближе к концу.
Геттеры и сеттеры
Геттеры и сеттеры не нужны для современной Java. У нас есть записи с Java 14, и Lombok по-прежнему хорош, несмотря на некоторые заявления об обратном. Единственная точка, где нам понадобятся геттеры/сеттеры, — это очень специфические настройки (например, JPA), где снова Lombok отлично решает проблему.
Статья выливается в тираду об отсутствии в Java функций синтаксического сахара. Это сделано намеренно. Вы можете взглянуть на Kotlin, если вас интересуют последние нюансы синтаксиса. Java — это «медленно и стабильно». Это хорошо и является основной причиной долголетия Java.
Синтаксический сахар и перегрузка операторов
Современная Java включает шаблоны в switch
, var
, многострочные строки и многое другое. Некоторые будущие функции включают шаблоны строк. Поддержка строковых шаблонов требует времени, потому что Java хочет сделать это правильно. Для этого есть некоторая поддержка на уровне API (и была уже некоторое время). Это неэффективно. Целью строковых шаблонов является создание радикально переопределяемого синтаксиса, который позволил бы такие вещи, как:
ResultSet rs = DB."SELECT * FROM Person p WHERE p.last_name = \{name}";
Обновление: с момента публикации этой статьи разработчики ошибочно предположили, что приведенный выше код является уязвимостью SQL-инъекций. Это не так. Это выглядит как замена строки, но это код, который использует этот синтаксис для создания параметризованного вызова SQL.
Обратите внимание, что name
— это переменная, которую компилятор будет проверять и динамически получать из области видимости!
DB
может быть индивидуально реализован разработчиком и не должен быть «встроенным», поэтому вы можете создавать сложные шаблоны прямо на месте.
Но давайте поговорим о той Java, которая у нас есть сегодня, а не о той, что будет через полгода. Использование append
не было рекомендацией для String
уже более десяти лет. Используйте +
, который наиболее эффективен и удобен для чтения. Что касается коллекций, разница между get()
и []
составляет буквально четыре символа. Эти персонажи имеют большое значение.
Мы можем легко переопределить это. Мы также можем понять семантические различия. Массивы Java очень быстрые; во многих случаях родная скорость быстрая. Сборы не могут быть такими быстрыми, что, как мы видим, очень ценно.
Тот факт, что операторы не могут быть перегружены, является огромным преимуществом. Если я вижу a + b
, я знаю, что это либо строка, либо число, а не какой-то скрытый метод. Это одна из самых сильных сторон Java и одна из причин, по которой она пользуется популярностью уже почти 30 лет, в то время как другие языки остаются в стороне. Синтаксис Java предназначен для чтения в масштабе.
Когда у вас есть проект с 1 миллионом строк кода или даже 100 тысячами, проблемы меняются. На данный момент трудно обнаружить, что программист X в модуле Y неправильно переопределил оператор, когда вы отлаживаете проблему. В этот момент синтаксис должен быть простым, и любые незначительные затраты, которые вы сэкономили изначально, будут оплачены с 10-кратным процентом. Определение простых флипов по мере того, как код становится более сложным и стареющим. Добавьте к этому возможности инструментов для анализа строгого простого кода в огромных масштабах, и это станет еще большим преимуществом.
Проверенные исключения
Проверяемые исключения являются необязательными. Но это одна из лучших функций Java. Так много кода неожиданно дает сбой. Когда вы строите что-то в качестве хобби, это может быть нормально. Если вы хотите создать профессиональное приложение, вам нужно обрабатывать каждую ошибку. Проверенные исключения помогут вам избежать этой чепухи. Люди ненавидят проверенные исключения из-за лени. Java защищает вас от самих себя.
Не должно быть случая, когда я устанавливаю сетевое соединение, соединение с БД, открываю файл и т. д., и мне не нужно обрабатывать потенциальную ошибку. Я могу это сделать, но затем проверенные исключения заставляют меня продолжать куда-то ставить. Это удивительная особенность.
Зависимости
У меня много проблем с Maven и Gradle. Но если вы сравните ее практически с любой другой системой зависимостей, у них все отлично. У них есть проблемы, но их нельзя сравнивать с чем-то молодым вроде карго, у которого почти нет пакетов в сравнении. Maven Central огромен: 27 терабайт jar-файлов и 496 миллиардов запросов. Он отлично работает и почти не имеет простоев.
Другие инструменты, такие как NPM, отлично демонстрируют сильные стороны maven. Если зависимости в maven являются проблемой, то NPM имеет 100-кратную проблему и не контролирует. По мере роста этих вещей возникают сложности. Особенно с несколькими версиями maven на рынке. Тем не менее, одна из вещей, которые есть у maven и gradle, — это инструменты. Во многих случаях интегрированные среды разработки помогают решать проблемы и сразу же находить решение.
Культурные проблемы на Яве
Вторая статья интереснее, и в какой-то степени я с ней согласен. Java-разработчики склонны превращать каждую проблему в более сложную. В некоторых случаях это необходимо, Java — это 800-килограммовая горилла среди платформ программирования, и ее решения часто перепроектированы. Это, как правило, лучше, чем недостаточная мощность, но имеет свою цену.
Зачем нужна аннотация для проверки
В статье действительно был приведен один интересный пример, который кажется «правильным» для случайного наблюдателя, но проблематичен.
@NotNull @Email
String noReplyEmailAddress
Автор утверждает, что это плохо и нужно реализовать кастомную типизацию, например:
Это вполне возможно в Java, поскольку приведенный выше код является допустимым кодом Java. Но у него есть несколько проблем, поэтому у нас есть проверка bean-компонентов.
- Это невозможно оптимизировать — фреймворк может поднять валидацию бина вверх по цепочке валидации. Его можно даже легко проверить в коде на стороне клиента, поскольку это декларативный API. Здесь нам нужно фактически выполнить конструктор для выполнения проверки.
- Декларативные аннотации можно перемещать вниз по цепочке для беспрепятственного применения ограничений базы данных и т. д.
- Мы можем применять несколько аннотаций одновременно
- Синтаксис лаконичнее
В результате аннотации могут показаться странными и не заставлять печатать. Это правда. Но они повышают производительность и мощность. За их использованием стоит много мыслей и здравого смысла. Я понимаю точку зрения автора: я тоже не большой поклонник IoC, но в данном конкретном случае он не прав.
Последние мысли
Эта статья потратила слишком много времени на оборону. Пришло время переключать передачи. Java существует уже почти 30 лет и до сих пор в основном совместима с Java 1.0. Это фантастика и бесподобно!
Одна из сильных сторон его консервативного подхода заключается в том, что он может выполнять удивительные оптимизации под капотом, и никто из вас не замечает, что происходит. Java 9 полностью заменил способ представления строк в памяти и значительно сократил использование оперативной памяти. Точно так же Loom повысит пропускную способность синхронных приложений Java. Valhalla еще больше улучшит производительность коллекции и объединит разделение объектов и примитивов. Панама окончательно избавит нас от JNI и сделает процесс интеграции с нативным кодом намного приятнее.
Приятно то, что JVM — это большая палатка. Если вы не являетесь поклонником Java, вам могут подойти Kotlin или Scala. Преимущество JVM применимо повсеместно, и большинство функций, которые я здесь упомянул, принесут пользу всей нашей совместной экосистеме.