Попробовал трезво порассуждать чего же в Java действительно не хватает, а если хватает, то работает не так. А то всякие выдуманные проблемы, как у Николая Палиенко не выдерживают критики.
Итак, порядок тут значения не имеет. Проблемы языка и платформы совмещены.
Java – это клей для связи одного xml с другим
Возможно так исторически сложилось, но xml’а в яве много, очень много. Это сейчас уже можно задеплоить простой сервлет без использования и строчки xml’a. До прошлого года это сделать было невозможно.
Проблема с xml – это то, что он плохо расширяется. Spring, Hibernate, сервлеты, JMS, JAXB, зависимости через Maven или через что-то другое – все это тянет за собой кучу xml’a, в котором трудно ориентироваться как только система начинает розрастаться.
Для борьбы с этим придумали java annotations и это действительно помогает, но не всегда. В Spring некоторые вещи можно делать пока только через xml.
Опять же в какой-то мере это проблема общая для всех платформ. На память приходит популярный веб-фреймворк на PHP – Symfony. Конфигов и там достаточно (пусть там и не xml, а yaml).
Модульность
Во-первых, программы/библиотеки на яве распространяются в виде JAR-файлов. Формат JAR был изобретен еще в середине 90-х и, по правде говоря, он не очень хорош ни как средство для дистрибуции библиотек, ни как средство для запуска программ (студентота, наверное, до сих пор спрашивает своих преподавателей: “WTF? Где мой .exe?”).
Основная проблема – jar-файлы не поддерживают версий и поэтому на них трудно ссылаться. Ссылаться же на них приходится, когда в дело вступают зависимости между jar’ами. И как следствие – необходимо ссылаться из classpath, т.е. вручную прописывая путь ко всем необходимым библиотеками при старте программы. Это pain in ass.
Для борьбы с этим были изобретены разные монструозные системы: OSGI, Maven, Ivy + Ant и так далее. Пока это помогает, но требует дополнительных усилий.
Verbosity – Многословие
Java не поддерживает first-class функций. Как следствие, не так такого понятия как функции высшего порядка, т.е. нельзя передать функции как один из аргументов или возвратить ее в качестве результата. Внутренние классы (анонимные) позволяют как обойти это ограничение, но это ведет к ненужной многословности.
Метапрограммирование
Проиллюстрирую на одной проблеме. В яве принято писать гетеры и сетеры. По стандарту они пишутся по одним и тем же правилам из года в год. Юнит-тесты к ним естественно никто не пишет, но ошибки все равно возникают. Кроме того это банально надоедает.
Если бы яве можно было расширить возможности языка и определить по умолчанию поведение для всяких get- и set-методов, это бы сохранило множество нервов.
К сожалению, сделать это без аннотаций, java reflection и тому подобных вещах – нельзя. Хотя такое дополнение к языку не помешало. Добавлять или вызывать методы динамично, в режиме runtime, в яве очень сложно и порой не хватает.
Возможно из-за этого недостатка фреймворки и любой другой generic код в яве выглядит громоздким и плодит ненужные иерархии классов.
Разные мелочи и досадные ошибки
Тут я просто пройдусь небольшим списком:
- массивы и примитивные типы – убрать, сделать только объекты
- checked exceptions – хорошо в теории, но на практике не работает
- generics – что с ними не так заслуживает отдельного поста
- многие базовые вещи занимают много времени – java.io, java.reflect
Заключение
Думаю, я вернусь еще к этому списку и буду время от времени дополнять его. В любом случае, у явы есть и свои преимущества. Статическая типизация, огромный набор тулз (поддержка IDE, профайлеры и прочее, прочее, прочее), богатая библиотека, сообщество и так далее. Но это тема для другого разговора.